fix: object validation collapsed (#416)
This commit is contained in:
parent
dad93b42fc
commit
d17378d557
@ -606,6 +606,27 @@ collections:
|
||||
name: thumb
|
||||
widget: image
|
||||
required: false
|
||||
- label: Collapsed, optional with required children
|
||||
name: collapsed_optional_with_required_children
|
||||
widget: object
|
||||
required: false
|
||||
collapsed: true
|
||||
fields:
|
||||
- name: layout
|
||||
widget: hidden
|
||||
default: post
|
||||
- label: Number of posts on frontpage
|
||||
name: front_limit
|
||||
widget: number
|
||||
required: true
|
||||
- label: Author
|
||||
name: author
|
||||
widget: string
|
||||
required: true
|
||||
- label: Thumbnail
|
||||
name: thumb
|
||||
widget: image
|
||||
required: true
|
||||
- name: relation
|
||||
label: Relation
|
||||
file: _widgets/relation.json
|
||||
|
@ -3,9 +3,13 @@ import { getDataPath } from '@staticcms/core/lib/i18n';
|
||||
import type { I18nSettings } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
export const getEntryDataPath = (i18n: I18nSettings | undefined) => {
|
||||
return (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
|
||||
};
|
||||
|
||||
export const selectFieldErrors =
|
||||
(path: string, i18n: I18nSettings | undefined) => (state: RootState) => {
|
||||
const dataPath = (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
|
||||
const dataPath = getEntryDataPath(i18n);
|
||||
const fullPath = `${dataPath.join('.')}.${path}`;
|
||||
return state.entryDraft.fieldsErrors[fullPath] ?? [];
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar
|
||||
import Outline from '@staticcms/core/components/UI/Outline';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
import { compileStringTemplate } from '@staticcms/core/lib/widgets/stringTemplate';
|
||||
import { getEntryDataPath } from '@staticcms/core/reducers/selectors/entryDraft';
|
||||
|
||||
import type { ObjectField, ObjectValue, WidgetControlProps } from '@staticcms/core/interface';
|
||||
import type { FC } from 'react';
|
||||
@ -61,7 +62,7 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
||||
hasErrors,
|
||||
value = {},
|
||||
}) => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [collapsed, setCollapsed] = useState(field.collapsed ?? false);
|
||||
|
||||
const handleCollapseToggle = useCallback(() => {
|
||||
setCollapsed(!collapsed);
|
||||
@ -75,6 +76,13 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
||||
|
||||
const multiFields = useMemo(() => field.fields, [field.fields]);
|
||||
|
||||
const childHasError = useMemo(() => {
|
||||
const dataPath = getEntryDataPath(i18n);
|
||||
const fullPath = `${dataPath}.${path}`;
|
||||
|
||||
return Boolean(Object.keys(fieldsErrors).find(key => key.startsWith(fullPath)));
|
||||
}, [fieldsErrors, i18n, path]);
|
||||
|
||||
const renderedField = useMemo(() => {
|
||||
return (
|
||||
multiFields?.map((field, index) => {
|
||||
@ -132,7 +140,7 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
||||
collapsed={collapsed}
|
||||
onCollapseToggle={handleCollapseToggle}
|
||||
heading={objectLabel}
|
||||
hasError={hasErrors}
|
||||
hasError={hasErrors || childHasError}
|
||||
t={t}
|
||||
testId="object-title"
|
||||
/>
|
||||
@ -140,7 +148,9 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
||||
<StyledFieldsBox $collapsed={collapsed} key="object-control-fields">
|
||||
{renderedField}
|
||||
</StyledFieldsBox>
|
||||
{forList ? null : <Outline key="object-control-outline" hasError={hasErrors} />}
|
||||
{forList ? null : (
|
||||
<Outline key="object-control-outline" hasError={hasErrors || childHasError} />
|
||||
)}
|
||||
</StyledObjectControlWrapper>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user