fix: list widget validation after sort (#3611)
This commit is contained in:
parent
72b26f4435
commit
3d0856ea88
@ -107,11 +107,12 @@ export default class ListControl extends React.Component {
|
|||||||
const { field, value } = props;
|
const { field, value } = props;
|
||||||
const allItemsCollapsed = field.get('collapsed', true);
|
const allItemsCollapsed = field.get('collapsed', true);
|
||||||
const itemsCollapsed = value && Array(value.size).fill(allItemsCollapsed);
|
const itemsCollapsed = value && Array(value.size).fill(allItemsCollapsed);
|
||||||
|
const keys = value && Array.from({ length: value.size }, () => uuid());
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
itemsCollapsed: List(itemsCollapsed),
|
itemsCollapsed: List(itemsCollapsed),
|
||||||
value: valueToString(value),
|
value: valueToString(value),
|
||||||
keys: List(),
|
keys: List(keys),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +173,10 @@ export default class ListControl extends React.Component {
|
|||||||
this.getValueType() === valueTypes.SINGLE
|
this.getValueType() === valueTypes.SINGLE
|
||||||
? this.singleDefault()
|
? this.singleDefault()
|
||||||
: fromJS(this.multipleDefault(field.get('fields')));
|
: fromJS(this.multipleDefault(field.get('fields')));
|
||||||
this.setState({ itemsCollapsed: this.state.itemsCollapsed.push(false) });
|
this.setState({
|
||||||
|
itemsCollapsed: this.state.itemsCollapsed.push(false),
|
||||||
|
keys: this.state.keys.push(uuid()),
|
||||||
|
});
|
||||||
onChange((value || List()).push(parsedValue));
|
onChange((value || List()).push(parsedValue));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,7 +191,10 @@ export default class ListControl extends React.Component {
|
|||||||
handleAddType = (type, typeKey) => {
|
handleAddType = (type, typeKey) => {
|
||||||
const { value, onChange } = this.props;
|
const { value, onChange } = this.props;
|
||||||
const parsedValue = fromJS(this.mixedDefault(typeKey, type));
|
const parsedValue = fromJS(this.mixedDefault(typeKey, type));
|
||||||
this.setState({ itemsCollapsed: this.state.itemsCollapsed.push(false) });
|
this.setState({
|
||||||
|
itemsCollapsed: this.state.itemsCollapsed.push(false),
|
||||||
|
keys: this.state.keys.push(uuid()),
|
||||||
|
});
|
||||||
onChange((value || List()).push(parsedValue));
|
onChange((value || List()).push(parsedValue));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -227,13 +234,17 @@ export default class ListControl extends React.Component {
|
|||||||
|
|
||||||
processControlRef = ref => {
|
processControlRef = ref => {
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
this.validations.push(ref.validate);
|
const {
|
||||||
|
validate,
|
||||||
|
props: { validationKey: key },
|
||||||
|
} = ref;
|
||||||
|
this.validations.push({ key, validate });
|
||||||
};
|
};
|
||||||
|
|
||||||
validate = () => {
|
validate = () => {
|
||||||
if (this.getValueType()) {
|
if (this.getValueType()) {
|
||||||
this.validations.forEach(validateListItem => {
|
this.validations.forEach(item => {
|
||||||
validateListItem();
|
item.validate();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.props.validate();
|
this.props.validate();
|
||||||
@ -265,12 +276,13 @@ export default class ListControl extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRemove = (index, event) => {
|
handleRemove = (index, key, event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const { itemsCollapsed } = this.state;
|
const { itemsCollapsed, keys } = this.state;
|
||||||
const { value, metadata, onChange, field, clearFieldErrors } = this.props;
|
const { value, metadata, onChange, field, clearFieldErrors } = this.props;
|
||||||
const collectionName = field.get('name');
|
const collectionName = field.get('name');
|
||||||
const isSingleField = this.getValueType() === valueTypes.SINGLE;
|
const isSingleField = this.getValueType() === valueTypes.SINGLE;
|
||||||
|
const validations = this.validations;
|
||||||
|
|
||||||
const metadataRemovePath = isSingleField ? value.get(index) : value.get(index).valueSeq();
|
const metadataRemovePath = isSingleField ? value.get(index) : value.get(index).valueSeq();
|
||||||
const parsedMetadata =
|
const parsedMetadata =
|
||||||
@ -278,17 +290,14 @@ export default class ListControl extends React.Component {
|
|||||||
? { [collectionName]: metadata.removeIn(metadataRemovePath) }
|
? { [collectionName]: metadata.removeIn(metadataRemovePath) }
|
||||||
: metadata;
|
: metadata;
|
||||||
|
|
||||||
// Removed item object index is the last item in the list
|
this.setState({ itemsCollapsed: itemsCollapsed.delete(index), keys: keys.delete(index) });
|
||||||
const removedItemIndex = value.count() - 1;
|
|
||||||
|
|
||||||
this.setState({ itemsCollapsed: itemsCollapsed.delete(index) });
|
|
||||||
|
|
||||||
onChange(value.remove(index), parsedMetadata);
|
onChange(value.remove(index), parsedMetadata);
|
||||||
clearFieldErrors();
|
clearFieldErrors();
|
||||||
|
|
||||||
// Remove deleted item object validation
|
// Remove deleted item object validation
|
||||||
if (this.validations) {
|
if (validations) {
|
||||||
this.validations.splice(removedItemIndex, 1);
|
this.validations = validations.filter(item => item.key !== key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -322,7 +331,7 @@ export default class ListControl extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSortEnd = ({ oldIndex, newIndex }) => {
|
onSortEnd = ({ oldIndex, newIndex }) => {
|
||||||
const { value } = this.props;
|
const { value, clearFieldErrors } = this.props;
|
||||||
const { itemsCollapsed, keys } = this.state;
|
const { itemsCollapsed, keys } = this.state;
|
||||||
|
|
||||||
// Update value
|
// Update value
|
||||||
@ -337,6 +346,10 @@ export default class ListControl extends React.Component {
|
|||||||
// Reset item to ensure updated state
|
// Reset item to ensure updated state
|
||||||
const updatedKeys = keys.set(oldIndex, uuid()).set(newIndex, uuid());
|
const updatedKeys = keys.set(oldIndex, uuid()).set(newIndex, uuid());
|
||||||
this.setState({ itemsCollapsed: updatedItemsCollapsed, keys: updatedKeys });
|
this.setState({ itemsCollapsed: updatedItemsCollapsed, keys: updatedKeys });
|
||||||
|
|
||||||
|
//clear error fields and remove old validations
|
||||||
|
clearFieldErrors();
|
||||||
|
this.validations = this.validations.filter(item => updatedKeys.includes(item.key));
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
@ -354,7 +367,7 @@ export default class ListControl extends React.Component {
|
|||||||
|
|
||||||
const { itemsCollapsed, keys } = this.state;
|
const { itemsCollapsed, keys } = this.state;
|
||||||
const collapsed = itemsCollapsed.get(index);
|
const collapsed = itemsCollapsed.get(index);
|
||||||
const key = keys.get(index) || `item-${index}`;
|
const key = keys.get(index);
|
||||||
let field = this.props.field;
|
let field = this.props.field;
|
||||||
|
|
||||||
if (this.getValueType() === valueTypes.MIXED) {
|
if (this.getValueType() === valueTypes.MIXED) {
|
||||||
@ -373,7 +386,7 @@ export default class ListControl extends React.Component {
|
|||||||
<StyledListItemTopBar
|
<StyledListItemTopBar
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
onCollapseToggle={partial(this.handleItemCollapseToggle, index)}
|
onCollapseToggle={partial(this.handleItemCollapseToggle, index)}
|
||||||
onRemove={partial(this.handleRemove, index)}
|
onRemove={partial(this.handleRemove, index, key)}
|
||||||
dragHandleHOC={SortableHandle}
|
dragHandleHOC={SortableHandle}
|
||||||
/>
|
/>
|
||||||
<NestedObjectLabel collapsed={collapsed}>{this.objectLabel(item)}</NestedObjectLabel>
|
<NestedObjectLabel collapsed={collapsed}>{this.objectLabel(item)}</NestedObjectLabel>
|
||||||
@ -397,6 +410,7 @@ export default class ListControl extends React.Component {
|
|||||||
fieldsErrors={fieldsErrors}
|
fieldsErrors={fieldsErrors}
|
||||||
ref={this.processControlRef}
|
ref={this.processControlRef}
|
||||||
controlRef={controlRef}
|
controlRef={controlRef}
|
||||||
|
validationKey={key}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ClassNames>
|
</ClassNames>
|
||||||
@ -407,15 +421,16 @@ export default class ListControl extends React.Component {
|
|||||||
renderErroneousTypedItem(index, item) {
|
renderErroneousTypedItem(index, item) {
|
||||||
const field = this.props.field;
|
const field = this.props.field;
|
||||||
const errorMessage = getErrorMessageForTypedFieldAndValue(field, item);
|
const errorMessage = getErrorMessageForTypedFieldAndValue(field, item);
|
||||||
|
const key = `item-${index}`;
|
||||||
return (
|
return (
|
||||||
<SortableListItem
|
<SortableListItem
|
||||||
css={[styles.listControlItem, styles.listControlItemCollapsed]}
|
css={[styles.listControlItem, styles.listControlItemCollapsed]}
|
||||||
index={index}
|
index={index}
|
||||||
key={`item-${index}`}
|
key={key}
|
||||||
>
|
>
|
||||||
<StyledListItemTopBar
|
<StyledListItemTopBar
|
||||||
onCollapseToggle={null}
|
onCollapseToggle={null}
|
||||||
onRemove={partial(this.handleRemove, index)}
|
onRemove={partial(this.handleRemove, index, key)}
|
||||||
dragHandleHOC={SortableHandle}
|
dragHandleHOC={SortableHandle}
|
||||||
/>
|
/>
|
||||||
<NestedObjectLabel collapsed={true} error={true}>
|
<NestedObjectLabel collapsed={true} error={true}>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user