Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add foundations for extensible validation in forms #6161

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/node_env_setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ runs:

- name: Install Volto dependencies
shell: bash
run: pnpm i
run: make install

- name: Install Cypress if not in cache
if: steps.cache-cypress-binary.outputs.cache-hit != 'true'
Expand Down
38 changes: 2 additions & 36 deletions .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -497,45 +497,11 @@ jobs:
steps:
- uses: actions/checkout@v4

# node setup
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
- name: Set up Node.js environment
uses: ./.github/actions/node_env_setup
with:
node-version: ${{ matrix.node-version }}

- name: Enable corepack
run: corepack enable

- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Cache Cypress Binary
id: cache-cypress-binary
uses: actions/cache@v4
with:
path: ~/.cache/Cypress
key: binary-${{ matrix.node-version }}-${{ hashFiles('pnpm-lock.yaml') }}

- run: pnpm i

- name: Build dependencies
run: pnpm build:deps

- name: Install Cypress if not in cache
if: steps.cache-cypress-binary.outputs.cache-hit != 'true'
working-directory: packages/volto
run: make cypress-install

# Generator own tests
- name: Generator tests
run: pnpm test
Expand Down
23 changes: 2 additions & 21 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,11 @@ jobs:
steps:
- uses: actions/checkout@v4

# node setup
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
- name: Set up Node.js environment
uses: ./.github/actions/node_env_setup
with:
node-version: ${{ matrix.node-version }}

- name: Enable corepack
run: corepack enable

- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- run: pnpm i

# Locales in place are needed for the tests to pass
- run: pnpm --filter @plone/volto i18n

Expand Down
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ clean: ## Clean development environment
find ./packages -name node_modules -exec rm -rf {} \;

.PHONY: install
install: build-deps ## Set up development environment
install: ## Set up development environment
# Setup ESlint for VSCode
node packages/scripts/vscodesettings.js
pnpm i
node packages/scripts/vscodesettings.js
make build-deps

##### Documentation

Expand Down Expand Up @@ -137,10 +138,10 @@ docs-test: docs-clean docs-linkcheckbroken docs-vale ## Clean docs build, then
cypress-install: ## Install Cypress for acceptance tests
$(NODEBIN)/cypress install

packages/registry/dist: packages/registry/src
packages/registry/dist: $(shell find packages/registry/src -type f)
pnpm build:registry

packages/components/dist: packages/components/src
packages/components/dist: $(shell find packages/components/src -type f)
pnpm build:components

.PHONY: build-deps
Expand Down
1 change: 1 addition & 0 deletions docs/source/configuration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ environmentvariables
expanders
locking
slots
validation
```
204 changes: 204 additions & 0 deletions docs/source/configuration/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---
myst:
html_meta:
"description": "Client side form field validation"
"property=og:description": "Client side form field validation"
"property=og:title": "Form fields validation"
"keywords": "Volto, Plone, frontend, React, configuration, form, fields, validation"
---

# Client side form field validation

Volto provides a mechanism for delivering form field validation in an extensible way.
This extensibility is based on the Volto component registry.

## Registering a validator
stevepiercy marked this conversation as resolved.
Show resolved Hide resolved

You can register a validator using the component registry API from your add-on configuration.
All validators are registered under the name `fieldValidator`.
The validators are registered using the `dependencies` array of the `registerComponent` API to differentiate the kind of validator to be registered.

### `default` validators

These validators are registered and applied to all fields.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, does "all" mean for all form blocks, or something else? I guess form blocks, but please correct me, if not.

Suggested change
These validators are registered and applied to all fields.
Default validators are registered and applied to all fields for all form blocks.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['default', 'minLength'],
component: minLengthValidator,
});
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the example after the explanation. It's jarring to throw an example before its description without some kind of introduction.


It takes two `dependencies` being the first element a fixed `default` identifier, and the second you can set it up to identify the validator itself.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to flesh out what the dependencies key actually means and how to use it.

  1. What's the purpose of the default identifier?
  2. Can I use more than two identifiers in the dependencies array?
Suggested change
It takes two `dependencies` being the first element a fixed `default` identifier, and the second you can set it up to identify the validator itself.
The `dependencies` key accepts an array of two values.
The first element has the identifier of `default`, and the second element has the identifier of the validator.
The second identifier can be any string.
In the following example, the second identifier is `minLength`.

In the case of the example, this other dependency is `minLength`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the case of the example, this other dependency is `minLength`.

It can be any string.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It can be any string.


### Per field `type` validators
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Per field `type` validators
### Field `type` validators


These validators are applied depending on the specified `type` of the field.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
These validators are applied depending on the specified `type` of the field.
Field `type` validators are applied according to the specified `type` of the field.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['integer', 'maximum'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the default is missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ummm, in that line, the default is not needed here, because it's not a default validator, it's a type one, so the first dependency is the name of the type.

component: maximumValidator,
});
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move examples after description.


It takes two `dependencies` since we can potentially have several validators for the same `type`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It takes two `dependencies` since we can potentially have several validators for the same `type`.
The following example shows that the field validation registration accepts an array of two string values for the `dependencies` key.
This allows you to have several different validators for the same `type`.

The first element should be the field `type`, and the second you should set it up to identify the validator itself.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first element should be the field `type`, and the second you should set it up to identify the validator itself.
The first element should be the field `type`.
The second identifier can be any string that represents the validator.

You should specify the `type` in the JSON schema of the block (in a content type, it is included in the default serialization of the field).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You should specify the `type` in the JSON schema of the block (in a content type, it is included in the default serialization of the field).
You can specify the `type` in the JSON schema of the block.
In a content type, the default serialization of the field includes the `type`.

If a field does not specify type, it assumes a `string` type as validator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If a field does not specify type, it assumes a `string` type as validator.
If you don't specify a field's `type`, the serializer uses a `string` type as the validator.

The next example is for the use case of JSON schema defined in a block:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The next example is for the use case of JSON schema defined in a block:
The following example shows how to use a JSON schema defined in a block.


```ts
let blockSchema = {
// ... fieldset definition in here
properties: {
...schema.properties,
customField: {
title: 'My custom field',
description: '',
type: 'integer',
},
},
required: [],
};
```

### Per field `widget` validators
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Per field `widget` validators
### Field `widget` validators


These validators are applied depending on the specified `widget` of the field.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
These validators are applied depending on the specified `widget` of the field.
Field `widget` validators are applied according to the specified `widget` for the field.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['phoneNumber', 'isValidPhone'],
component: phoneValidator,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes this a widget validator instead of a type validator?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move example after narrative text.

```

It takes two `dependencies` since we can potentially have several validators for the same `widget`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It takes two `dependencies` since we can potentially have several validators for the same `widget`.
The following example shows that the widget validation registration accepts an array of two string values for the `dependencies` key.
This allows you to have several different validators for the same `type`.

The first element should be the name of the `widget`, and the second you can set it up to identify the validator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first element should be the name of the `widget`, and the second you can set it up to identify the validator.
The first element should be the name of the `widget`.
The second identifier can be any string that represents the validator.

You should specify the `widget` in the JSON schema of the block (or as additional data in the content type definition).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You should specify the `widget` in the JSON schema of the block (or as additional data in the content type definition).
You should specify the `widget` in the JSON schema of the block, or as additional data in the content type definition.

The next example is for the use case of a block JSON schema:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The next example is for the use case of a block JSON schema:
The following example shows how to use a JSON schema defined in a block.


```ts
let blockSchema = {
// ... fieldset definition in here
properties: {
...schema.properties,
phone: {
title: 'Phone number',
description: '',
widget: 'phoneNumber',
},
},
required: [],
};
```

### Per behavior and field name validator
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Per behavior and field name validator
### Behavior and field name validator


These validators are applied depending on the behavior (usually coming from a content type definition) in combination with the name of the field.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
These validators are applied depending on the behavior (usually coming from a content type definition) in combination with the name of the field.
Behavior and field name validators are applied according to the behavior combined with the name of the field.
The behavior usually comes from a content type definition.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['plone.eventbasic', 'start', 'startValidator'],
component: startEventDateRangeValidator,
});
```

The first dependency should be the name of the behavior, and the second the name (`id`) of the field.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first dependency should be the name of the behavior, and the second the name (`id`) of the field.
The `dependencies` key accepts an array of two or three values.
The first element is a string that is the name of the behavior.
The second element is the name (`id`) of the field.

It can get a third dependency in case you want to specify several validators for the same behavior - field id combination.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It can get a third dependency in case you want to specify several validators for the same behavior - field id combination.
If you want to specify several validators for the same behavior, you can provide an optional third dependency as a field id combination.

This type of validator only applies to content-type validators.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This type of validator only applies to content-type validators.
This type of validator applies only to content type validators.


### Per block type and field name validator
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Per block type and field name validator
### Block type and field name validator


These validators are applied depending on the block type in combination with the name of the field in the block settings JSON schema.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
These validators are applied depending on the block type in combination with the name of the field in the block settings JSON schema.
Block type and field name validators are applied according to the block type combined with the name of the field in the block settings JSON schema.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['slider', 'url', 'isURL'],
component: urlValidator,
});
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move example after description.


The first dependency should be the `id` of the block, and the second the `id` of the field.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it the @type of the block?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first dependency should be the `id` of the block, and the second the `id` of the field.
The `dependencies` key accepts an array of two values.
The first element is a string that is the `type` of the block.
The second element is the `id` of the field.

It can get a third dependency in case you want to specify several validators for the same block type - field id combination.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It can get a third dependency in case you want to specify several validators for the same block type - field id combination.
To specify several validators for the same block type, you can provide an optional third value as a field id combination.

This type of validator only applies to blocks.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This type of validator only applies to blocks.
This type of validator applies only to blocks.


### Specific validator using the `validator` key in the field

A final type of validator is applied to the field if the `validator` key is present in the JSON schema definition of the form field.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A final type of validator is applied to the field if the `validator` key is present in the JSON schema definition of the form field.
You can apply a specific validator to a field by using the `validator` key in the JSON schema definition of the form field.


```ts
config.registerComponent({
name: 'fieldValidator',
dependencies: ['isURL'],
component: urlValidator,
});
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move after description.


The dependencies take one single name, in this case, the name of the validator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The dependencies take one single name, in this case, the name of the validator.
The `dependencies` key accepts an array with a single value, the name of the validator.

You should specify the validator in the JSON schema of the block (or as additional data in the content type definition).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You should specify the validator in the JSON schema of the block (or as additional data in the content type definition).
You should specify the validator either in the JSON schema of the block or as additional data in the content type definition.


```ts
let blockSchema = {
// ... fieldset definition in here
properties: {
...schema.properties,
customField: {
title: 'Default field',
description: '',
validator: 'isURL',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe allow passing directly a validator function as well? We're way past the point "schemas should be serializable" and for one-offs it's easier to declare them inline.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the pattern we are teaching is go for "named" components and call them by name (partially because of the duality forms from the backend/content types and the client defined forms in blocks), I'd refrain to do so, because then we will have two use cases, one where you can do it, and another use case in which you can't.

Also, in terms of explaining this in docs will became tricky and separate this is already confusing (I've been there when reviewing this with @ericof). Some other considerations is testability, because in that regard, modularization >> inlining things.

So, in principle, I would be -1 for this.

},
},
required: [],
};
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move example after description.


It does not need to be tied to any field `type` or `widget` definition.
It runs in addition to all the above, so it complements the other validators if any apply.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My biggest piece of feedback on this overall is using an array for the dependencies feels like trying to fit a square peg into a round hole. It's quite hard to keep track of all the different ways validators can be registered and which values need to go in the dependencies for each one. And it also seems to be like there might be some ambiguous cases, like if there is a field type and a widget type with the same name.

I don't know if the registry supports this but would it be possible to make things a bit more explicit by specifying the dependencies as an object instead of an array? So for example:

config.registerComponent({
  name: 'fieldValidator',
  dependencies: {
    blockType: 'slider',
    fieldName: 'url',
    validatorName: 'isURL',
  },
  component: urlValidator,
});

Copy link
Member Author

@sneridagh sneridagh Jul 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davisagli TBH, I'm not fully satisfied with it... I thought that the reason was mainly because we can't get it to work as satisfying as the ZCA works :) As you know, I initially envisioned and implemented the resolution algorithm using a string and concating the deps if we have an array, so I've played with that concept, even in the new getComponents registry API method.

Using an object would be possible too, I guess. I can play with the idea, and leave the original API in place also.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davisagli I did an initial implementation of using an object instead of an array but I have doubts on how to hash the resultant key to store that object, so then getComponents work in the same simple way, under the same concepts that we had before. It does work, but under some assumptions that I do not like or they are not satisfactory/safe :/

Maybe if you have some time, we can talk about it.


## Volto's default validators

Volto provides a set of validators by default, you can find them in this module: `packages/volto/src/config/validators.ts`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Volto provides a set of validators by default, you can find them in this module: `packages/volto/src/config/validators.ts`
Volto provides a set of validators.
You can find them in the module {file}`packages/volto/src/config/validators.ts`.
```{todo}
Document the API as a reference in another file, after the dust settles.
```


### How to override them
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### How to override them
### Override Volto's default validators


You can override them in your add-on as any other component defined in the registry, by redefining them using the same `dependencies`, and providing your own.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can override them in your add-on as any other component defined in the registry, by redefining them using the same `dependencies`, and providing your own.
You can override Volto's default validators in your add-on as any other component defined in the registry.
To do so, use the `dependencies` key, and provide your own values.
```{todo}
Provide usage example.
```


## Signature of a validator

A validator has the following signature:

```ts
type Validator = {
// The field value
value: string;
// The field schema definition object
field: Record<string, any>;
// The form data
formData?: any;
// The intl formatMessage function
formatMessage: Function;
};
```

This is an example of an `isNumber` validator:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This is an example of an `isNumber` validator:
The following example shows an `isNumber` validator.


```ts
export const isNumber = ({ value, formatMessage }: Validator) => {
const floatRegex = /^[+-]?\d+(\.\d+)?$/;
const isValid =
typeof value === 'number' && !isNaN(value) && floatRegex.test(value);
return !isValid ? formatMessage(messages.isNumber) : null;
};
```

Using the `formData` you can perform validation checks using other field data as source.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Using the `formData` you can perform validation checks using other field data as source.
Using `formData`, you can perform validation checks between multiple fields' data.

This is interesting in the case that two fields are related, like `start` and `end` dates.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This is interesting in the case that two fields are related, like `start` and `end` dates.
This is useful when you need to compare the values of multiple fields, such as ensuring that the end date and time of an event is after its start.
```{todo}
Provide usage example.
```

7 changes: 7 additions & 0 deletions docs/source/upgrade-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,13 @@ It is unlikely that your code uses it, unless you heavily customized the Jest te
This was not used by the core since some time ago, and nowadays is more suitable for being an add-on and not being included in core.
If you still use it, bring it back as your main add-on dependency, bring back the `SocialSharing` component from Volto 17 as a custom component in your add-on code.

### Refactor of `FormValidation` module

The `packages/volto/src/helpers/FormValidation/FormValidation.jsx` module has been heavily refactored.
Some helper functions have been moved to `packages/volto/src/helpers/FormValidation/validators.ts`, however, none of those functions were exported in the first place, so no imports will be broken.
stevepiercy marked this conversation as resolved.
Show resolved Hide resolved
In case that you've shadowed the `packages/volto/src/helpers/FormValidation/FormValidation.jsx` module, you should revisit it and update it with the latest refactor.
stevepiercy marked this conversation as resolved.
Show resolved Hide resolved
If you added more validators manually in that shadow, please refer to the documentation to add the validators in the new way: {doc}`../configuration/validation`.
stevepiercy marked this conversation as resolved.
Show resolved Hide resolved

(volto-upgrade-guide-17.x.x)=

## Upgrading to Volto 17.x.x
Expand Down
12 changes: 10 additions & 2 deletions packages/coresandbox/src/components/Blocks/TestBlock/Data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import { BlockDataForm } from '@plone/volto/components/manage/Form';
import type { BlockEditProps } from '@plone/types';

const TestBlockData = (props: BlockEditProps) => {
const { block, blocksConfig, contentType, data, navRoot, onChangeBlock } =
props;
const {
block,
blocksConfig,
contentType,
data,
navRoot,
onChangeBlock,
errors,
} = props;
const intl = useIntl();
const schema = blocksConfig[data['@type']].blockSchema({ intl, props });

Expand All @@ -24,6 +31,7 @@ const TestBlockData = (props: BlockEditProps) => {
blocksConfig={blocksConfig}
navRoot={navRoot}
contentType={contentType}
errors={errors}
/>
);
};
Expand Down
10 changes: 9 additions & 1 deletion packages/coresandbox/src/components/Blocks/TestBlock/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ export const multipleFieldsetsSchema: BlockConfigBase['blockSchema'] = ({
title: 'fourth',
fields: ['href', 'firstWithDefault', 'style'],
},
{
id: 'fifth',
title: 'fifth',
fields: ['fieldRequiredInFieldset'],
},
],
properties: {
slides: {
Expand Down Expand Up @@ -232,6 +237,9 @@ export const multipleFieldsetsSchema: BlockConfigBase['blockSchema'] = ({
title: 'HTML',
widget: 'richtext',
},
fieldRequiredInFieldset: {
title: 'Field required in fieldset',
},
},
required: [],
required: ['fieldRequiredInFieldset'],
});
1 change: 1 addition & 0 deletions packages/registry/news/6161.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `getComponents` that match a partial set of dependencies, given a name. @sneridagh
Loading
Loading