-
-
Notifications
You must be signed in to change notification settings - Fork 714
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add the docs of custom schema and variations
- Loading branch information
Showing
1 changed file
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
--- | ||
myst: | ||
html_meta: | ||
"description": "Volto block with custom schema and view components using variations" | ||
"property=og:description": "Volto block with custom schema and view components using variations" | ||
"property=og:title": "Volto block with custom schema and variations" | ||
"keywords": "Volto, React, blocks, grid, container, Plone" | ||
--- | ||
|
||
(custom-schema-view-and-variations)= | ||
|
||
# Block with a custom schema and variations | ||
|
||
We can create a block that uses `variations`. A {term}`variation` is an alternative view of a block. This variation is shown as an additional option in the schema editor and lets the webmaster to change how this block is viewed. Think of it as a different view of the same block | ||
|
||
What we need to do is to define the schema, the view component, the variations and configure the block settings. | ||
|
||
## Preparations | ||
|
||
In your volto addon, create a folder inside the {file}`components` folder to save all the files required to create a block. | ||
|
||
Name this folder as {file}`ExampleBlock`. | ||
|
||
## Schema | ||
|
||
Create a {file}`Schema.js` file inside the {file}`ExampleBlock` folder, with the following contents: | ||
|
||
```js | ||
import messages from './messages'; | ||
|
||
const Schema = ({ intl }) => { | ||
return { | ||
title: intl.formatMessage(messages.block02), | ||
block: 'block05', | ||
fieldsets: [ | ||
{ | ||
id: 'default', | ||
title: intl.formatMessage(messages.default), | ||
fields: ['url', 'title'], | ||
}, | ||
], | ||
|
||
properties: { | ||
url: { | ||
title: intl.formatMessage(messages.URL), | ||
widget: 'url', | ||
}, | ||
title: { | ||
title: intl.formatMessage(messages.title), | ||
}, | ||
}, | ||
required: [], | ||
}; | ||
}; | ||
|
||
export default Schema; | ||
``` | ||
|
||
## Messages | ||
|
||
As you have noted, we have prepared the block to be internationalized, {term}`internanationalization` (i18n), is the process of creating user interfaces which are suitable for different languages and cultural contexts. | ||
|
||
So we need a file {file}`messages.js` in the same {file}`ExampleBlock` folder with the following contents: | ||
|
||
```js | ||
import { defineMessages } from 'react-intl'; | ||
|
||
const messages = defineMessages({ | ||
block05: { | ||
id: 'block05', | ||
defaultMessage: 'Block 05', | ||
}, | ||
default: { | ||
id: 'default', | ||
defaultMessage: 'Default', | ||
}, | ||
URL: { | ||
id: 'URL', | ||
defaultMessage: 'URL', | ||
}, | ||
title: { | ||
id: 'title', | ||
defaultMessage: 'Title', | ||
}, | ||
}); | ||
|
||
export default messages; | ||
``` | ||
|
||
## View component | ||
|
||
In this case, as we are using variations, the view component needs to use the variation template to render the contents of the block. | ||
|
||
This is easily achieved using the `variation` coming on the `props` of the block. | ||
|
||
Create a file {file}`View.jsx` in the {file}`ExampleBlock` folder with the following contents: | ||
|
||
```jsx | ||
import withBlockExtensions from '@plone/volto/helpers/Extensions/withBlockExtensions'; | ||
import cx from 'classnames'; | ||
import React from 'react'; | ||
|
||
const View = (props) => { | ||
// data holds the values entered in the block edit form | ||
// className holds the CSS class names injected to this block by Volto's `styleClassNameExtenders` | ||
// style holds the CSS properties injected to this block by Volto's `Block Sytle Wrapper` | ||
// variation holds the variation selected in the block editor, and it is an object as defined in the block configuration | ||
const { data, className, style, variation } = props; | ||
|
||
const BodyTemplate = variation?.template; | ||
|
||
return ( | ||
<div | ||
className={cx( | ||
'block', | ||
'block05', | ||
`block05-variation-${variation?.id}`, | ||
className, | ||
)} | ||
style={style} | ||
> | ||
<BodyTemplate data={data} /> | ||
</div> | ||
); | ||
}; | ||
// the `withBlockExtensions` HOC, makes the variation selector available in the block edit form | ||
// and provides the `variation` property in the props. | ||
export default withBlockExtensions(View); | ||
``` | ||
## Variations | ||
Now we need to create one or more variations that will be available for this block. | ||
Create a file {file}`Variation01.jsx` in the {file}`ExampleBlock` folder with the following contents: | ||
```jsx | ||
import React from 'react'; | ||
const View = (props) => { | ||
const { data } = props; | ||
return ( | ||
<> | ||
<h2>Variation View 01</h2> | ||
<div> | ||
<ul> | ||
<li>Title: {data.title}</li> | ||
<li>URL: {data.url}</li> | ||
</ul> | ||
</div> | ||
</> | ||
); | ||
}; | ||
export default View; | ||
``` | ||
Create a file {file}`Variation02.jsx` in the {file}`ExampleBlock` folder with the following contents: | ||
```jsx | ||
import React from 'react'; | ||
const View = (props) => { | ||
const { data } = props; | ||
return ( | ||
<> | ||
<h2>Variation View 02</h2> | ||
<div> | ||
<ul> | ||
<li>Title: {data.title}</li> | ||
<li>URL: {data.url}</li> | ||
</ul> | ||
</div> | ||
</> | ||
); | ||
}; | ||
export default View; | ||
``` | ||
As you can see, in this case the variations are pretty much the same, the only difference is the text that is rendered in the `<h2>` tag. But it can be anything. | ||
## Block configuration | ||
With all the block components ready, you need to register the block into Volto. | ||
To do so, open your addon's {file}`index.js` file, that will have the following contents: | ||
```js | ||
const applyConfig = (config) => { | ||
config.settings.isMultilingual = false; | ||
config.settings.supportedLanguages = ['en']; | ||
config.settings.defaultLanguage = 'en'; | ||
return config; | ||
} | ||
export default applyConfig; | ||
``` | ||
And before the last `return config;` statement, write the following configuration: | ||
```js | ||
config.blocks.blocksConfig.block05 = { | ||
id: 'block05', // this is the block id, it must match the id on the previous line | ||
title: 'Block 05', // this is the block title | ||
view: View05, // this is the block's view component | ||
//edit: Edit05, | ||
blockSchema: Schema05, // this is the schema that will be used to render the edit form | ||
icon: imagesSVG, // this is the image that will be shown in the block selector | ||
sidebarTab: 1, // this is set to 1 to have the `Block` tab selected in the sidebar editor when editing this block | ||
// these are the variations available for this block | ||
variations: [ | ||
{ | ||
id: 'variation01', // this is the id of the variation | ||
title: 'Variation 01', // this is the title of the variation | ||
isDefault: true, // this signals if this is the default variation for this block | ||
template: VariationView0501, // this is the component that will render the variation | ||
}, | ||
{ | ||
id: 'variation02', | ||
title: 'Variation 02', | ||
isDefault: false, | ||
template: VariationView0502, | ||
}, | ||
], | ||
}; | ||
``` | ||
|
||
On the top of the file you will need to import the relevant components, as follows: | ||
|
||
```js | ||
import View05 from './components/ExampleBlock/View'; | ||
import Schema05 from './components/ExampleBlock/Schema'; | ||
import VariationView0501 from './components/ExampleBlock/VariationView01'; | ||
import VariationView0502 from './components/ExampleBlock/VariationView02'; | ||
// This is the icon we use for the example, use a meaningful one or provide your own image. | ||
import imagesSVG from '@plone/volto/icons/images.svg'; | ||
``` | ||
|
||
## See it in action | ||
|
||
Your block is ready to be used in your site. | ||
|
||
Restart your Volto site and you will be able to add it using the block add form. |