- Documentation >
- Content management >
- Forms >
- Create 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 will learn how to create the new Form with richtext_description
attribute that allows you to add formatted
description to the Form.
To create a richtext_description
attribute,
add the following configuration to config/packages/ibexa.yaml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | ibexa_form_builder:
fields:
checkbox_with_richtext_description:
name: Checkbox with RichtextDescription
category: Default
thumbnail: '/bundles/ibexaadminui/img/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: ibexa.form_builder.field_mapper }
ibexa.form_builder.attribute_form_type_mapper.richtext_description:
class: Ibexa\FormBuilder\Form\Mapper\FieldAttribute\GenericFieldAttributeTypeMapper
arguments:
$formTypeClass: App\FormBuilder\Form\Type\FieldAttribute\AttributeRichtextDescriptionType
$typeIdentifier: 'richtext_description'
tags:
- { name: ibexa.form_builder.form.type.attribute.mapper }
App\FormBuilder\FormSubmission\Converter\RichtextDescriptionFieldSubmissionConverter:
arguments:
$typeIdentifier: 'checkbox_with_richtext_description'
$twig: '@twig'
tags:
- { name: ibexa.form_builder.field_submission_converter }
|
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 Ibexa\FieldTypeRichText\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';
}
}
|
The templates for the forms should look as follows:
templates/bundles/IbexaFormBuilderBundle/fields/config/form_fields.html.twig
:
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 | {% extends "@!IbexaFormBuilder/fields/config/form_fields.html.twig" %}
{% block _field_configuration_attributes_richtext_description_row %}
<fieldset class="fb-config-field fb-config-field--action form-group" data-field-value="{{form.vars.value.value}}">
<section class="ibexa-fieldgroup container">
<div class="ibexa-content-field">
<div class="ibexa-content-field-value">
<div class="col-12">
<div class="ibexa-data-source">
{% set udw_context = {
'languageCode': 'en',
} %}
{{ form_errors(form) }}
{{ form_widget(form, {'attr': {'class': 'vidar-textarea d-none'}}) }}
<div class="hidden" data-udw-config-name="richtext_embed" data-udw-config="{{ ibexa_udw_config('richtext_embed', udw_context) }}"></div>
<div class="hidden" data-udw-config-name="richtext_embed_image" data-udw-config="{{ ibexa_udw_config('richtext_embed_image', udw_context) }}"></div>
<div class="ibexa-data-source__richtext border px-3 py-3" id="rich_text_content_vl1__editable"></div>
{{ form_rest(form) }}
</div>
{{ encore_entry_link_tags('ibexa-richtext-onlineeditor-css', null, 'richtext') }}
{{ encore_entry_script_tags('ibexa-richtext-onlineeditor-js', null, 'richtext') }}
{{ encore_entry_script_tags('formbuilder-richtext-checkbox-js') }}
</div>
</div>
</div>
</section>
</fieldset>
{% endblock %}
|
templates/formtheme/formbuilder_checkbox_with_richtext_description.html.twig
:
| {% block checkbox_with_richtext_description_row %}
{{ form_label(form)}}
{{ form_errors(form) }}
{{ form_widget(form) }}
{{ form.vars.richtextDescription|ibexa_richtext_to_html5() }}
{% endblock %}
|
Add scripts
Now you need to enable the RichText editor. Provide the required script in a new src/public/js/formbuilder-richtext-checkbox.js
file:
| (function(global, doc, ibexa) {
const richtext = new ibexa.BaseRichText();
// Enable editor in all ibexa-data-source divs
doc.querySelectorAll('.ibexa-data-source').forEach((ibexaDataSource) => {
const richtextContainer = ibexaDataSource.querySelector(".ibexa-data-source__richtext");
const alloyEditor = richtext.init(richtextContainer);
});
})(window, window.document, window.ibexa);
|
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 getIbexaConfig = require('./ibexa.webpack.config.js');
const ibexaConfig = getIbexaConfig(Encore);
const customConfigs = require('./ibexa.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('./src/public/js/formbuilder-richtext-checkbox.js')
]);
// .autoProvidejQuery();
const projectConfig = Encore.getWebpackConfig();
projectConfig.name = 'app';
module.exports = [ ibexaConfig, ...customConfigs, projectConfig ];
// uncomment this line if you've commented-out the above lines
// module.exports = [ eZConfig, ibexaConfig, ...customConfigs ];
|
Clear the cache and regenerate the assets by running the following commands:
| 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 | <?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();
$dom->loadXML($options['richtext_description']);
$view->vars['richtextDescription'] = $dom;
}
}
|
Implement field mapper
To implement a field mapper, 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 Ibexa\Contracts\FormBuilder\FieldType\Model\Field;
use Ibexa\FormBuilder\FieldType\Field\Mapper\GenericFieldMapper;
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 submission converter
The new Field is based on a checkbox, so to display the submissions of this field, you can use the BooleanFieldSubmissionConverter
.
Create a src/FormBuilder/FormSubmission/Converter/RichtextDescriptionFieldSubmissionConverter.php
file.
| <?php declare(strict_types=1);
namespace App\FormBuilder\FormSubmission\Converter;
use Ibexa\FormBuilder\FormSubmission\Converter\BooleanFieldSubmissionConverter;
class RichtextDescriptionFieldSubmissionConverter extends BooleanFieldSubmissionConverter
{
}
|
Now you can go to Back Office and build a new form.
In the left menu select Forms, click Create content and select Form.
You should be able to see the new section in the list of available fields:
