Magento 2.4.3 Page Builder – Fix WYSIWYG/Textarea Showing Full Master.html

configurationmagento2.4.3page-builderwysiwygxml

I have created a custom pagebuilder component with a WYSIWYG editor (also tried with Textarea), but after saving the page in admin, the WYSIWYG is showing the full html output from master.html

I would like to know what could I've possibly done wrong that this is happening. To me it looks like I'm missing some sort of configuration, so that the Form in admin knows where to find the correct editor content.

Some screenshots to show what I mean:

Before saving
enter image description here

After saving (and the page reloaded)
enter image description here

What you see in the second screenshot is the full HTML like it is rendered in frontend (frontend works fine by the way)

Below are the form and config XML files.
Note: I've removed most of the other elements which are working fine.

view/adminhtml&/pagebuilder/ls_teaser.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_PageBuilder:etc/content_type.xsd">
    <type name="ls_teaser"
          label="LS::Teaser"
          component="Magento_PageBuilder/js/content-type"
          preview_component="LS_CustomPageBuilder/js/content-type/ls-teaser/preview"
          form="pagebuilder_ls_teaser_form"
          menu_section="ls_elements"
          icon="icon-pagebuilder-image"
          sortOrder="10"
          translate="label">
        <children default_policy="deny"/>
        <appearances>
            <appearance default="true"
                        name="default"
                        preview_template="LS_CustomPageBuilder/content-type/ls-teaser/default/preview"
                        master_template="LS_CustomPageBuilder/content-type/ls-teaser/default/master"
                        reader="Magento_PageBuilder/js/master-format/read/configurable">
                <elements>
                    <element name="main">
                        <html name="content" preview_converter="Magento_PageBuilder/js/converter/html/directive"/>
                    </element>
                </elements>
            </appearance>
        </appearances>
        <additional_data>
            <item name="wysiwygConfig" xsi:type="array">
                <item name="wysiwygConfigData" xsi:type="object">Magento\PageBuilder\Model\Config\ContentType\AdditionalData\Provider\Wysiwyg\Config</item>
                <item name="parentSelectorsToUnderlay" xsi:type="array">
                    <item name="0" xsi:type="string">.teaser-headline</item>
                </item>
            </item>
        </additional_data>
    </type>
</config>

view/adminhtml/ui_component/pagebuilder_ls_teaser_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd" extends="pagebuilder_base_form">
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">pagebuilder_ls_teaser_form.pagebuilder_ls_teaser_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Teaser</item>
    </argument>
    <settings>
        <namespace>pagebuilder_ls_teaser_form</namespace>
        <deps>
            <dep>pagebuilder_ls_teaser_form.pagebuilder_ls_teaser_form_data_source</dep>
        </deps>
    </settings>
    <dataSource name="pagebuilder_ls_teaser_form_data_source">
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_PageBuilder/js/form/provider</item>
            </item>
        </argument>
        <dataProvider name="pagebuilder_ls_teaser_form_data_source" class="Magento\PageBuilder\Model\ContentType\DataProvider">
            <settings>
                <requestFieldName/>
                <primaryFieldName/>
            </settings>
        </dataProvider>
    </dataSource>
    <fieldset name="appearance_fieldset" sortOrder="10" component="Magento_PageBuilder/js/form/element/dependent-fieldset">
        <settings>
            <label translate="true">Appearance</label>
            <additionalClasses>
                <class name="admin__fieldset-visual-select-large">true</class>
            </additionalClasses>
            <collapsible>false</collapsible>
            <opened>true</opened>
            <imports>
                <link name="hideFieldset">${$.name}.appearance:options</link>
                <link name="hideLabel">${$.name}.appearance:options</link>
            </imports>
        </settings>
        <field name="appearance" formElement="select" sortOrder="10" component="Magento_PageBuilder/js/form/element/dependent-visual-select">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="default" xsi:type="string">default</item>
                </item>
            </argument>
            <settings>
                <additionalClasses>
                    <class name="admin__field-wide">true</class>
                    <class name="admin__field-visual-select-container">true</class>
                </additionalClasses>
                <dataType>text</dataType>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                </validation>
                <elementTmpl>Magento_PageBuilder/form/element/visual-select</elementTmpl>
            </settings>
            <formElements>
                <select>
                    <settings>
                        <options class="AppearanceSourceLsTeaser" />
                    </settings>
                </select>
            </formElements>
        </field>
    </fieldset>
    <fieldset name="general" sortOrder="20">
        <settings>
            <label/>
        </settings>
        <field name="content" formElement="wysiwyg">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">page</item>
                    <item name="wysiwygConfigData" xsi:type="array">
                        <item name="is_pagebuilder_enabled" xsi:type="boolean">false</item>
                        <item name="toggle_button" xsi:type="boolean">true</item>
                        <item name="add_widgets" xsi:type="boolean">false</item>
                        <item name="add_images" xsi:type="boolean">false</item>
                        <item name="add_variables" xsi:type="boolean">false</item>
                        <item name="height" xsi:type="string">100px</item>
                    </item>
                </item>
            </argument>
            <settings>
                <additionalClasses>
                    <class name="admin__field-wide">true</class>
                </additionalClasses>
                <label/>
                <dataScope>content</dataScope>
            </settings>
            <formElements>
                <wysiwyg>
                    <settings>
                        <wysiwyg>true</wysiwyg>
                        <rows>8</rows>
                    </settings>
                </wysiwyg>
            </formElements>
        </field>
    </fieldset>
</form>

Best Answer

Okay, found out how it's working and answering my own question in case someone else has this problem.

How to correctly add html content in your custom component?

In our example we will add a headline with WYSIWYG editor.

view/adminhtml/pagebuilder/content_type/component_name.xml

This is the config file where you "define" the datastore used in knockout js (preview.html and master.html)

Our html element, which we can use as html="data.headline.html" in our knockout files is defined as well.

<element name="headline">
    <html name="content" preview_converter="Magento_PageBuilder/js/converter/html/directive"/>
</element>

view/adminhtml/ui_component/pagebuilder_component_name_form.xml

Here we define the element for the form used in pagebuilder to add your content. The fieldset doesn't matter, important thins is to have the forrect field name. In our case <field name="content ...

        <field name="content" formElement="wysiwyg">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">page</item>
                    <item name="wysiwygConfigData" xsi:type="array">
                        <item name="is_pagebuilder_enabled" xsi:type="boolean">false</item>
                        <item name="toggle_button" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
            <settings>
                <additionalClasses>
                    <class name="admin__field-wide">true</class>
                </additionalClasses>
                <label/>
                <dataScope>content</dataScope>
            </settings>
            <formElements>
                <wysiwyg>
                    <settings>
                        <wysiwyg>true</wysiwyg>
                    </settings>
                </wysiwyg>
            </formElements>
        </field>

view/adminhtml/web/template/content-type/component_name/default/master.html

This file defines how the HTML of your component will be rendered on frontend side. And also, and that's the important part, based on this file the pagebuilder will get the actual data to display in it's form!

Most importantly, if you wanna add your html content with html="data.headline.html" you also HAVE to add the attributes with attr="data.headline.attributes"!

Even so you don't have defined any attributes in your config, magento still adds the element type which is needed to correctly get the html contents back into the right form field! If you don't add the attributes to you html element, your form field will be populated with the wrong or no data at all.

<div attr="data.main.attributes" ko-style="data.main.style" css="data.main.css" class="bypass-html-filter">

    <div
        attr="data.headline.attributes" // <-- this is needed and was missing in my case
        html="data.headline.html"
    />
    
    <!-- other html content -->

</div>