Skip to content

Validation internal blocks onSubmit form. #6776

Open
@alexandreIFB

Description

@alexandreIFB

Is your feature request related to an issue? Please describe.

Initial issue:

Block validations are not working properly inside inline blocks, such as Grid, Column, and others.

For simulate:

It is possible to simulate with any block that has validation within the Grid. I recommend using the Teaser block that comes natively, as it requires an href.

Root cause:

Validation in the onSubmit method inside the Form is only applied to blocks at the root of the structure, meaning that inner blocks inside inline components are not validated.

onSubmit(event) {
const formData = this.state.formData;
if (event) {
event.preventDefault();
}
const errors = this.props.schema
? FormValidation.validateFieldsPerFieldset({
schema: this.props.schema,
formData,
formatMessage: this.props.intl.formatMessage,
})
: {};
let blocksErrors = {};
if (hasBlocksData(formData)) {
// Validate blocks
const blocks = this.state.formData[getBlocksFieldname(formData)];
const blocksLayout =
this.state.formData[getBlocksLayoutFieldname(formData)];
const defaultSchema = {
properties: {},
fieldsets: [],
required: [],
};
blocksLayout.items.forEach((block) => {
let blockSchema =
config.blocks.blocksConfig[blocks[block]['@type']].blockSchema ||
defaultSchema;
if (typeof blockSchema === 'function') {
blockSchema = blockSchema({
intl: this.props.intl,
formData: blocks[block],
});
}
const blockErrors = FormValidation.validateFieldsPerFieldset({
schema: blockSchema,
formData: blocks[block],
formatMessage: this.props.intl.formatMessage,
});
if (keys(blockErrors).length > 0) {
blocksErrors = {
...blocksErrors,
[block]: { ...blockErrors },
};
}
});
}

Another test I performed was the validation within the Column block from the @eeacms/volto-columns-block community.

Passing errors from props in Container Edit:

Another issue is that error properties inside ContainerEdit are not being passed to BlockForm.

Solution suggestion

A potential solution would be to create a recursive helper function, such as blockValidator, that checks for the presence of the blocks and blocks_layout fields in a block. This function should be able to validate inner blocks up to a depth of level 1, ensuring that inner errors are detected and handled better.

Problems that may arise that could be addressed with this solution:

Error differentiation:

It is important to differentiate internal errors from regular block errors. One possible approach could be to give internal errors a specific key, such as @internal_blocks. This would allow for proper handling, especially when setting up the error toast and moving focus to the correct element.

} else if (keys(blocksErrors).length > 0) {
const errorField = Object.entries(
Object.entries(blocksErrors)[0][1],
)[0][0];
const errorMessage = Object.entries(
Object.entries(blocksErrors)[0][1],
)[0][1];
toast.error(
<Toast
error
title={this.props.intl.formatMessage(
messages.blocksFieldsErrorTitle,
{ errorField },
)}
content={errorMessage}
/>,
);
this.props.setSidebarTab(1);
this.props.setUIState({
selected: Object.keys(blocksErrors)[0],
multiSelected: [],
hovered: null,
});
}

Visibility of errors in internal block forms:

Another problem arises when internal block forms fail to detect the associated errors due to the dependency on element IDs in the root blocksErrors object. A fix could be to add internal block errors to the root structure, (this would be duplicated both at the root and within the parent block with the @internal_blocks key) ensuring that they are identified and displayed correctly. (This workaround may not be ideal, but it avoids major changes and significant impacts to the rest of the system.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions