<< ALL BLOG POSTS

Improving the Edit Block in Volto

|
August 31, 2021
Table of Contents

In Getting Started with Custom Blocks in Volto, we walked through the basic structure setup for a custom block and registered it with Plone’s React-based frontend, Volto. Now, let’s review the simple Edit Component in src/components/Blocks/MyCustomBlock/

Edit.jsx 

import React from 'react';
const Edit = props => {
  return <div>I'm the Block edit component!</div>;
};
export default Edit;

Currently, the Edit Block displays the text “I'm the Block edit component!,” but there’s not a way to actually edit anything. Don’t worry — Volto’s Sidebarportal component can be used to extend the Edit component.

Using the Sidebar panel

When in Edit mode, the right sidebar panel (separate from main body of the page) displays additional information. The right sidebar panel typically features a Document tab which addresses the overall page and a Block tab which displays information specific to the selected Block.

First, add the SidebarPortal component to Edit.jsx. Everything inside the SidebarPortal will be displayed in the right sidebar panel. Next, you’ll need to destructure selected, onChangeBlock, block, data from props to support the Block’s functionality.

Visit the Volto Developer Documentation for a complete list of props.

Edit.jsx

import { SidebarPortal } from '@plone/volto/components';
...
const Edit = props => {
  const { selected, onChangeBlock, block, data } = props;
  return (
    <div>
      <SidebarPortal selected={selected}>
        I'm the Sidebar panel!
      </SidebarPortal>
      <div>I'm the Block edit component!</div>
    </div>
  )
};

pVrsxGxI.png

Screenshot of Volto Edit mode. In the right sidebar panel, the Block tab is selected. “I’m the Sidebar Panel!” is displayed in the Block tab.


Before building the form, let’s move the Sidebar code into its own component to keep things neat and organized.

Create Data.jsx in src/components/Blocks/MyCustomBlock/.

Data.jsx 

import React from 'react';

const Data = (props) => {
  const { block, data, onChangeBlock } = props;
  return (
    <>
      I'm the Sidebar panel woo!
    </>
  );
};
export default Data;

Next, Import Data.jsx into Edit.jsx. Then, replace the contents of Sidebarportal with the Data component. The Data component will need access to the Block data, so the Data component will also need to be passed to the Edit component’s props.

Edit.jsx

import Data from './Data';
...
const Edit = props => {
  const { selected, onChangeBlock, block, data } = props;
  return (
    <div>
      <SidebarPortal selected={selected}>
        <Data
            {...props}
            data={data}
            block={block}
            onChangeBlock={onChangeBlock}
          />
      </SidebarPortal>
      <div>I'm the Block edit component!</div>
    </div>
  )
};

Defining the Edit form

The Edit form can be created with either the InlineForm or the BlockDataForm component. Since I plan to use a schema-based form, I chose to use the BlockDataForm component.BlockDataForm is a convenience component that wraps the InlineForm component with withVariationSchemaEnhancer. This allows for easy use of Volto Extensions such as variations and schema enhancers.

First, Schema.js will need to be created in src/components/Blocks/MyCustomBlock/ to store the form schema.

Schema.js

export const DataSchema = (props) => {
  return {
    title: 'My Custom Blocks Form',
    fieldsets: [
      {
        id: 'default',
        title: 'Default',
        fields: ['href', 'title', 'subtitle', 'bg_image', 'openLinkInNewTab'],
      },
    ],
    properties: {
      href: {
        title: 'Link',
        widget: 'object_browser',
        mode: 'link',
        selectedItemAttrs: [
          'Title',
          'Description',
        ],
        allowExternals: true,
      },
      title: {
        title: 'Title',
      },
      subtitle: {
        title: 'Subtitle Text',
        widget: 'textarea',
      },
      bg_image: {
        title: 'Background Image',
        widget: 'object_browser',
        mode: 'image',
        allowExternals: true,
      },
      openLinkInNewTab: {
        title: 'Open Link in New Tab',
        type: 'boolean',
      },
    },
    required: [],
  };
};

The Link and Background Images fields use Volto’s ObjectBrowserWidget to find content within the site. The default mode forObjectBrowserWidget is multiple, but, in this scenario,ObjectBrowserWidget is using the link and image mode to limit the fields. Visit Volto’s Developer Documentation to learn more about ObjectBrowserWidget and its settings.

Next, we import Schema.js into the Data component.

Data.jsx

import { BlockDataForm } from '@plone/volto/components';
import { DataSchema } from './schema';
...
const Data = (props) => {
  const { block, data, onChangeBlock } = props;
  const schema = DataSchema({ ...props });
  return (
      <BlockDataForm
        schema={schema}
        title={schema.title}
        onChangeField={(id, value) => {
          onChangeBlock(block, {
            ...data,
            [id]: value,
          });
        }}
        formData={data}
        block={block}
      />
  );
};
export default Data;

Now, you have the Edit form displayed in the sidebar panel. 

 rBSPrH7E.png

Tips for Leveraging Volto

Share your Volto projects with us, and sign up for our newsletters to get the latest tech tips in your inbox. 

Related Posts
How can we assist you?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.