Skip to content

Create Form Builder Form attribute

You can create a Form attribute for new Form fields or existing ones. To do it, you have to define a new Form attribute in the configuration.

In the following example you can create new Form with richtext_description attribute that allows you to add formatted description to the Form.

Configure Form attribute

To create a richtext_description attribute, provide the following configuration in config/packages/ezplatform.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
ez_platform_form_builder:
    fields:
        checkbox_with_richtext_description:
            name: Checkbox with Text
            category: Default
            thumbnail: '/bundles/ezplatformadminui/img/ez-icons.svg#input-line'
            attributes:
                label:
                    name: Label
                    type: string
                    validators:
                        not_blank:
                            message: You must provide label of the field
                richtext_description:
                    name: 'Description'
                    type: 'richtext_description'
            validators:
                required: ~

Create mapper

The new Form attribute requires a FieldAttributeTypeMapper. Register the mapper as a service in config/services.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    App\FormBuilder\FieldType\Field\Mapper\CheckboxWithRichtextDescriptionFieldMapper:
        arguments:
            $fieldIdentifier: checkbox_with_richtext_description
            $formType: 'App\FormBuilder\Form\Type\CheckboxWithRichtextDescriptionType'
        tags:
            - { name: ezplatform.form_builder.field_mapper }

    ezplatform.form_builder.attribute_form_type_mapper.richtext_description:
        class: EzSystems\EzPlatformFormBuilder\Form\Mapper\FieldAttribute\GenericFieldAttributeTypeMapper
        arguments:
            $formTypeClass: App\FormBuilder\Form\Type\FieldAttribute\AttributeRichtextDescriptionType
            $typeIdentifier: 'richtext_description'
        tags:
            - { name: ezplatform.form_builder.attribute_form_type_mapper }

    App\FormBuilder\FormSubmission\Converter\RichtextDescriptionFieldSubmissionConverter:
        arguments:
            $typeIdentifier: 'checkbox_with_richtext_description'
            $twig: '@twig'
        tags:
            - { name: ezplatform.form_builder.field_submission_converter }

Add Symfony form type

The attribute needs to be editable for the form creator, so it needs to have a Symfony form type. Add an AttributeRichtextDescriptionType.php file with the form type in the src/FormBuilder/Form/Type/FieldAttribute directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php declare(strict_types=1);

namespace App\FormBuilder\Form\Type\FieldAttribute;

use EzSystems\EzPlatformRichText\Form\Type\RichTextType;
use Symfony\Component\Form\AbstractType;

class AttributeRichtextDescriptionType extends AbstractType
{
    /**
     * @return string|null
     */
    public function getParent()
    {
        return RichTextType::class;
    }

    /**
     * @return string
     */
    public function getBlockPrefix()
    {
        return 'field_configuration_attribute_richtext';
    }
}

Customize Form templates

The template files for the front end should look as follows:

  • templates/bundles/EzPlatformFormBuilderBundle/fields/config/form_fields.html.twig:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{% extends "@!EzPlatformFormBuilder/fields/config/form_fields.html.twig" %}
{% block _field_configuration_attributes_richtext_description_row %}
    <fieldset class="fb-config-field form-group" data-field-value="{{form.vars.value.value}}">
        {% set udw_context = {
            'languageCode': 'en',
        } %}
        {{ form_errors(form) }}

        <div class="hidden" data-udw-config-name="richtext_embed" data-udw-config="{{ ez_udw_config('richtext_embed', udw_context) }}"></div>
        <div class="hidden" data-udw-config-name="richtext_embed_image" data-udw-config="{{ ez_udw_config('richtext_embed_image', udw_context) }}"></div>

        {{ form_row(form) }}

        {{ encore_entry_script_tags('formbuilder-richtext-checkbox-js') }}
    </fieldset>
{% endblock %}
  • templates/formtheme/formbuilder_checkbox_with_richtext_description.html.twig:
1
2
3
4
5
6
{% block checkbox_with_richtext_description_row %}
    {{ form_label(form)}}
    {{ form_errors(form) }}
    {{ form_widget(form) }}
    {{ form.vars.richtextDescription|ez_richtext_to_html5() }}
{% endblock %}

Then, specify the new template in configuration, under the twig.form_themes configuration key:

1
2
3
twig:
    form_themes:
        - 'themes/<your-theme>/formtheme/formbuilder_checkbox_with_richtext_description.html.twig'

Add scripts

Now you need to enable the RichText editor. Provide the required script in a new src/Resources/public/js/formbuilder-richtext-checkbox.js file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(function (global, doc, eZ) {
    global.addEventListener('load', (event) => {
        const richtext = new eZ.BaseRichText();

        // Enable editor in all ez-data-source divs
        doc.querySelectorAll('.ez-data-source').forEach(
            (ezDataSource) => {
                const richtextContainer = ezDataSource.querySelector(
                    '.ez-data-source__richtext'
                );

                if (!richtextContainer || richtextContainer.hasAttribute('contenteditable')) {
                    return;
                }

                richtext.init(richtextContainer);
            }
        );
    });

    const openUdw = (config) => {
        const openUdwEvent = new CustomEvent('ez-open-udw', { detail: config });

        doc.body.dispatchEvent(openUdwEvent);
    };

    eZ.addConfig('richText.alloyEditor.callbacks.selectContent', openUdw);
})(window, window.document, window.eZ);

Then, paste the highlighted part of the code into the webpack.config.js file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const Encore = require('@symfony/webpack-encore');
const path = require('path');
const getEzConfig = require('./ez.webpack.config.js');
const eZConfigManager = require('./ez.webpack.config.manager.js');
const eZConfig = getEzConfig(Encore);
const customConfigs = require('./ez.webpack.custom.configs.js');

Encore.reset();
Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .enableStimulusBridge('./assets/controllers.json')
    .enableSassLoader()
    .enableReactPreset()
    .enableSingleRuntimeChunk()
    .copyFiles({
        from: './assets/images',
        to: 'images/[path][name].[ext]',
        pattern: /\.(png|svg)$/
    })
    .configureBabel((config) => {
        config.plugins.push('@babel/plugin-proposal-class-properties');
    })

    // enables @babel/preset-env polyfills
    .configureBabelPresetEnv((config) => {
        config.useBuiltIns = 'usage';
        config.corejs = 3;
    })
;

// Welcome page stylesheets
Encore.addEntry('welcome_page', [
    path.resolve(__dirname, './assets/scss/welcome-page.scss'),
]);

Encore.addEntry('app', './assets/app.js');

Encore.addEntry('formbuilder-richtext-checkbox-js', [
    path.resolve(__dirname, './src/Resources/public/js/formbuilder-richtext-checkbox.js')
]);

const projectConfig = Encore.getWebpackConfig();

projectConfig.name = 'app';

module.exports = [ eZConfig, ...customConfigs, projectConfig ];

// uncomment this line if you've commented-out the above lines
// module.exports = [ eZConfig, ...customConfigs ];

Clear the cache and regenerate the assets by running the following commands:

1
2
3
php bin/console cache:clear
php bin/console assets:install
yarn encore dev

Implement Field

Now you have to implement the Field, and make sure the value from the RichText attribute is passed on to the field form.

Create a src/FormBuilder/Form/Type/CheckboxWithRichtextDescriptionType.php file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php declare(strict_types=1);

namespace App\FormBuilder\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CheckboxWithRichtextDescriptionType extends AbstractType
{
    /**
     * @return string|null
     */
    public function getParent()
    {
        return CheckboxType::class;
    }

    /**
     * @return string
     */
    public function getBlockPrefix()
    {
        return 'checkbox_with_richtext_description';
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'richtext_description' => '',
        ]);
        $resolver->setAllowedTypes('richtext_description', ['null', 'string']);
    }

    public function buildView(FormView $view, FormInterface $form, array $options): void
    {
        // pass the Dom object of the richtext doc to the template
        $dom = new \DOMDocument();
        if (!empty($options['richtext_description'])) {
            $dom->loadXML($options['richtext_description']);
        }
        $view->vars['richtextDescription'] = $dom;
    }
}

Implement FieldMapper

To implement a FieldMapper, create a src/FormBuilder/FieldType/Field/Mapper/CheckboxWithRichtextDescriptionFieldMapper.php file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php declare(strict_types=1);

namespace App\FormBuilder\FieldType\Field\Mapper;

use EzSystems\EzPlatformFormBuilder\FieldType\Field\Mapper\GenericFieldMapper;
use EzSystems\EzPlatformFormBuilder\FieldType\Model\Field;

class CheckboxWithRichtextDescriptionFieldMapper extends GenericFieldMapper
{
    /**
     * {@inheritdoc}
     */
    protected function mapFormOptions(Field $field, array $constraints): array
    {
        $options = parent::mapFormOptions($field, $constraints);
        $options['label'] = $field->getAttributeValue('label');
        $options['richtext_description'] = $field->getAttributeValue('richtext_description');

        return $options;
    }
}

Now, the attribute value can be stored in the new Form.

Create SubmissionConverter

The new Field is based on checkbox, so to display the submissions of this field, you can use the BooleanFieldSubmissionConverter.

Create a src/FormBuilder/FormSubmission/Converter/RichtextDescriptionFieldSubmissionConverter.php file.

1
2
3
4
5
6
7
8
9
<?php declare(strict_types=1);

namespace App\FormBuilder\FormSubmission\Converter;

use EzSystems\EzPlatformFormBuilder\FormSubmission\Converter\BooleanFieldSubmissionConverter;

class RichtextDescriptionFieldSubmissionConverter extends BooleanFieldSubmissionConverter
{
}

Now you can go to Back Office and build a new form.

You should be able to see the new section in the list of available fields:

New form