0
votes

Currently I'm building my first gutenberg block. Everything seems fine, except the editor field shows the h2 and the p element double. Is there something I am missing?

I've searched the entire internet for the issue, but I was not able to find a solution to this problem.

enter image description here

Below you will see my Gutenberg code i've wrote. Maybe I am missing something? Or there is a typo?

/**
 * Block dependencies
 */
import icons from './icons';
import './editor.scss';

/**
 * Internal block libraries
 */
const { __ } = wp.i18n;
const {
    registerBlockType,
} = wp.blocks;

const {
  InspectorControls,
  RichText,
  MediaUpload,
} = wp.editor;

const {
    Tooltip,
    PanelBody,
    PanelRow,
    FormToggle,
    Button,
} = wp.components;

/**
 * Register example block
 */
export default registerBlockType('mfgb/banner', {
        title: __( 'Banner Block', 'mfgb' ),
        description: __( 'Voeg een banner toe aan de website (met of zonder tekst)', 'mfgb'),
        category: 'common',
        icon: {
            background: 'rgba(254, 243, 224, 0.52)',
            src: icons.upload,
        },
        keywords: [
            __( 'Image', 'mfgb' ),
            __( 'MediaUpload', 'mfgb' ),
            __( 'Message', 'mfgb' ),
        ],
        attributes: {
            title: {
                type: 'array',
                source: 'children',
                selector: 'h2',
            },
            content: {
                type: 'array',
                source: 'children',
                selector: 'p',
            },
            backgroundImage: {
                type: 'string',
                default: '', // no image by default!
            },
            contentControl: {
                type: 'boolean',
                default: false,
            },
        },

        edit: props => {

          const { attributes: { title, content, backgroundImage, contentControl, Component },
              className, setAttributes } = props;

          const toggleContentControl = () => setAttributes( { contentControl: ! contentControl } );

          function onTitleChange(changes) {
            setAttributes({
                title: changes
            });
          }

          function onContentChange(changes) {
            setAttributes({
                content: changes
            });
          }

          function onImageSelect(imageObject) {
            setAttributes({
                backgroundImage: imageObject.sizes.full.url
            })
          }

          return ([
            <InspectorControls>

              <PanelBody
                  title={ __( 'Tekst opties', 'mfgb' ) }
              >
                  <PanelRow>
                      <label
                          htmlFor="has-text-form-toggle"
                      >
                          { __( 'Bevat deze banner tekst?', 'mfgb' ) }
                      </label>
                      <FormToggle
                          id="has-text-form-toggle"
                          label={ __( 'Bevat tekst...', 'mfgb' ) }
                          checked={ contentControl }
                          onChange={ toggleContentControl }
                      />
                  </PanelRow>
              </PanelBody>

              <PanelBody
                  title={ __( 'Selecteer een achtergrond afbeelding', 'mfgb' ) }
              >
                <PanelRow>
                    <MediaUpload
                        onSelect={onImageSelect}
                        type="image"
                        value={backgroundImage} // make sure you destructured backgroundImage from props.attributes!
                        render={ ( { open } ) => (
                            <Button
                                className={ "button button-large" }
                                onClick={ open }
                            >
                                { icons.upload }
                                { __( ' Upload Image', 'mfgb' ) }
                            </Button>
                        ) }
                    />
                    <img src={backgroundImage} />
                </PanelRow>
            </PanelBody>

            </InspectorControls>,
            <div
                className={className}
                style={{
                    backgroundImage: `url(${backgroundImage})`,
                    backgroundSize: 'cover',
                    backgroundPosition: 'center'
                }}>
                <div className="overlay"></div> {/* Adding an overlay element */}

                { contentControl == true &&
                  <div>
                    <RichText
                        tagName="h2"
                        className="title" // adding a class we can target
                        value={title}
                        onChange={onTitleChange}
                        placeholder="Voer de titel in"
                    />
                    <RichText
                        tagName="p"
                        className="content" // adding a class we can target
                        value={content}
                        onChange={onContentChange}
                        placeholder="Voer de text in..."
                    />
                </div>
                }

            </div>
          ]);
        },
        save: props => {
          const { attributes, className } = props;
          const { title, content, contentControl, backgroundImage } = props.attributes;

          return (
              <div
              className={className}
              style={{
                    backgroundImage: `url(${backgroundImage})`,
                    backgroundSize: 'cover',
                    backgroundPosition: 'center'
                }}>
                  <div className="overlay"></div>
                  {/* the class also needs to be added to the h2 for RichText */}
                  { contentControl == true && (
                  <h2 class="title">{title}</h2>
                  )}
                  { contentControl == true && (
                  <p class="content">{content}</p>
                  )}
              </div>
          );
        },
    },
);
2

2 Answers

1
votes

One issue I see is that the default value for backgroundImage being set to null versus '' through an error for me. When I changed the backgroundImage to the following it worked:

backgroundImage: {
  type: 'string',
  default: '', // no image by default!
},

I wasn't able to duplicate the problem with two items in the editor. It only showed one for me.

It is worth noting though that rendering RichText content in the save setting works a little different than how you have it. It should be

<RichText.Content
  tagName="h2"
  value={ title }
/>

More information on RichText here in the Gutenberg Handbook

0
votes

I’ve been through the same situation a few times already, and after struggling with it for a while, I realized the issue was usually caused by custom CSS, specifically by the margin-top property.

It is the normal behavior to have two “repeated” elements, since the first holds the content that you manually input, and the other one works as a placeholder. When the placeholder is visible because there is no custom content in the first element, this last one receives a position: absolute which causes that odd behavior. After you manually insert some content, the placeholder disappears along with the issue. If you empty the field, the placeholder and the issue come back again.

So in conclusion, avoid margin-top for elements that play along with placeholders. Hope they can find a different approach for this because sometimes it’s kind of limiting to avoid using something that shouldn’t be causing trouble.

Hope that helps :)