it-swarm.com.de

Validierungsfehler: Erweiterung des Gutenberg-Galerieblocks

Ich versuche, den Gutenberg-Block core/gallery zu erweitern, um meiner Bildergalerie im Frontend einige neue Funktionen hinzuzufügen. Ich habe ein separates Plugin erstellt, um diese Aufgabe zu erledigen. Ich habe mein Skript mit folgendem Code registriert:

function mt_enqueue_gutenberg(){

  wp_enqueue_script(
        'mt-gallery-block',
        plugins_url( 'gallery-block.js',__FILE__),
        array( 'wp-blocks', 'wp-i18n', 'wp-element' )
    );

    //Script and stylesheet loaded on frontend only
    if(!is_admin()){
      wp_enqueue_script(
        'mt-gallery-frontend-script',
        plugins_url( 'gallery.js', __FILE__),
        array( 'mt-gallery-block' )
      );

      wp_enqueue_style(
        'mt-gallery-frontend-style',
        plugins_url( 'gallery.css', __FILE__),
        array( 'mt-gallery-block' )
      );
    }
}

add_action( 'enqueue_block_editor_assets', 'mt_enqueue_gutenberg');

In meiner gallery-block.js-Datei verwende ich den blocks.getSaveElement-Filter, um die Ausgabe des Blocks HTML- auf dem Frontend zu bearbeiten.

//Filter hook
wp.hooks.addFilter(
    'blocks.getSaveElement',
    'wpse-298225',
    mt_gallerySaveElement
)

function mt_gallerySaveElement( element, blockType, attributes ) {
    //returns the element without changing it, if it is not the gallery block
    if ( blockType.name !== 'core/gallery' ) {
        return element;
    }

    //Creates div element with nested img's
    var newElement = wp.element.createElement(
        'div',
        {
            'className': 'gallery-grid',
            'data-total-slides': attributes.images.length
        },
        //Loops through each image in the gallery and creates an img-element
        attributes.images.map(
            function( image, index ) {
              return wp.element.createElement(
                        'img',
                        {
                            'src': image.url,
                            'alt': image.alt,
                            'className': 'gallery-item',
                            'data-slide-no': index,
                            'data-caption': image.caption[0]
                        }
                    )

              }

        )
    )

    return newElement
}

Alles funktioniert so, wie es soll, außer wenn ich den Gutenberg-Editor neu lade. Wenn ich die Seite neu lade, wird ein Überprüfungsfehler angezeigt und ich darf den Galerieblock nicht bearbeiten. (Siehe Screenshots unten)

 Gallery block - before and after reload 

Unten habe ich einen Screenshot des Konsolenprotokolls bereitgestellt, nachdem ich die Seite neu geladen habe:

 Validation error - console log 

Ich bin mir ziemlich sicher, dass der Fehler auftritt, da meine Ausgabe nicht der erwarteten Struktur der Galerie entspricht und WordPress daher beim Neuladen der Seite keine Bilder im Galerieblock sieht.

Meine Frage lautet also: Wie kann ich diesen Überprüfungsfehler beheben?

Angenommen, der Fehler wird durch den Unterschied zwischen meiner HTML-Struktur und der erwarteten Galerie-Struktur verursacht: Wie kann ich Gutenberg meine HTML-Struktur als Galerie erkennen lassen?

Anregungen wäre sehr dankbar. ????

5
Andreas

Beantwortung meiner eigenen Frage:

Wie von WebElaine vorgeschlagen, habe ich einen völlig neuen Block erstellt, um das Problem zu beheben. Um diese Aufgabe zu vereinfachen, habe ich create-guten-block von Ahmad Awais verwendet, was ziemlich einfach einzurichten ist.

In init.php habe ich dafür gesorgt, dass mein JavaScript und zusätzliches CSS für das Frontend in die Warteschlange gestellt werden. Dies sollte einfach sein. Ich empfehle das Lesen der Learning Gutenberg-Serie auf css-tricks.com . Es war eine große Hilfe für mich, als ich anfing.

Der wichtige Teil ist, wie ich den Galerieblock erstellt habe. In block.js (erstellt von create-guten-block) habe ich MediaUpload von wp.editor und Button von wp.components destrukturiert.

const { MediaUpload } = wp.editor; //Import MediaUpload from wp.editor
const { Button } = wp.components; //Import Button from wp.components

Ich registriere den Block mit einem Titel, einem Symbol, einer Kategorie, einigen Schlüsselwörtern und einem Bildattribut mit dem Typarray. Dies wird die Bilder aus der Galerie enthalten

 registerBlockType( 'cgb/block-my-test-block', {
    title: __( 'MT - Gallery' ), // Block title.
    icon: 'format-gallery', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
    category: 'common', // Block category
    keywords: [ //Keywords
        __('materialtheme'),
        __('photos'),
        __('images')
    ],
    attributes: { //Attributes
        images : { //Images array
            type: 'array',
        }
},

Meine Bearbeitungsfunktion (der Teil des Blocks, der im Editor angezeigt wird) sieht folgendermaßen aus:

edit({ attributes, className, setAttributes }) {

        //Destructuring the images array attribute
        const {images = []} = attributes;


        // This removes an image from the gallery
        const removeImage = (removeImage) => {
                    //filter the images
                    const newImages = images.filter( (image) => {
                        //If the current image is equal to removeImage the image will be returnd
                        if(image.id != removeImage.id) {
                            return image;
                        }
                    });

                    //Saves the new state
                    setAttributes({
                        images:newImages,
                    })
        }


        //Displays the images
        const displayImages = (images) => {
            return (
                //Loops throug the images
                images.map( (image) => {
                    return (
                    <div className="gallery-item-container">
                            <img className='gallery-item' src={image.url} key={ images.id } />
                            <div className='remove-item' onClick={() => removeImage(image)}><span class="dashicons dashicons-trash"></span></div>
                            <div className='caption-text'>{image.caption[0]}</div>
                    </div>
                    )
                })

            )
        }

        //JSX to return
        return (
            <div>
                <div className="gallery-grid">
                    {displayImages(images)}
                </div>
                <br/>
                <MediaUpload
                        onSelect={(media) => {setAttributes({images: [...images, ...media]});}}
                        type="image"
                        multiple={true}
                        value={images}
                        render={({open}) => (
                            <Button className="select-images-button is-button is-default is-large" onClick={open}>
                                Add images
                            </Button>
                        )}
                    />
            </div>

        );
    },

Hier benutze ich das Objekt MediaUpload und Button. Beachten Sie, dass ich multiple auf true gesetzt habe, wodurch ich mehrere Bilder auswählen kann. Um auf diese Weise mehrere Bilder auszuwählen, müssen Sie gedrückt halten CTRL Als würden Sie mehrere Dateien im Datei-Explorer (unter Windows) auswählen.

In meiner Speicherfunktion ordne ich die Bilder zu und füge die gewünschten Attribute dem Tag img- hinzu.

save({attributes}) {
    //Destructuring the images array attribute
    const { images = [] } = attributes;

    // Displays the images
    const displayImages = (images) => {
        return (
            images.map( (image,index) => {
                return (
                        <img
                            className='gallery-item'
                            key={images.id}
                            src={image.url}
                            data-slide-no={index}
                            data-caption={image.caption[0]}
                            alt={image.alt}
                            />
                )
            })
        )
    }

    //JSX to return
    return (
        <div>
        <div className="gallery-grid" data-total-slides={images.length}>{ displayImages(images) }</div>
        </div>
    );

},

Mein vollständiger Code aus block.js sieht folgendermaßen aus:

/**
 * BLOCK: my-test-block
 *
 * Registering a basic block with Gutenberg.
 * Simple block, renders and saves the same content without any interactivity.
 */

import './style.scss';
import './editor.scss';

const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
const { MediaUpload } = wp.editor; //Import MediaUpload from wp.editor
const { Button } = wp.components; //Import Button from wp.components


/**
 * Register: aa Gutenberg Block.
 *
 * Registers a new block provided a unique name and an object defining its
 * behavior. Once registered, the block is made editor as an option to any
 * editor interface where blocks are implemented.
 *
 * @link https://wordpress.org/gutenberg/handbook/block-api/
 * @param  {string}   name     Block name.
 * @param  {Object}   settings Block settings.
 * @return {?WPBlock}          The block, if it has been successfully
 *                             registered; otherwise `undefined`.
 */

registerBlockType( 'cgb/block-my-test-block', {
    title: __( 'MT - Gallery' ), // Block title.
    icon: 'format-gallery', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
    category: 'common', // Block category
    keywords: [ //Keywords
        __('materialtheme'),
        __('photos'),
        __('images')
    ],
    attributes: { //Attributes
        images : { //Images array
            type: 'array',
        }
},

    /**
     * The edit function describes the structure of your block in the context of the editor.
     * This represents what the editor will render when the block is used.
     *
     * The "edit" property must be a valid function.
     *
     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
     */
    edit({ attributes, className, setAttributes }) {

        //Destructuring the images array attribute
        const {images = []} = attributes;


        // This removes an image from the gallery
        const removeImage = (removeImage) => {
                    //filter the images
                    const newImages = images.filter( (image) => {
                        //If the current image is equal to removeImage the image will be returnd
                        if(image.id != removeImage.id) {
                            return image;
                        }
                    });

                    //Saves the new state
                    setAttributes({
                        images:newImages,
                    })
        }


        //Displays the images
        const displayImages = (images) => {
            return (
                //Loops throug the images
                images.map( (image) => {
                    return (
                    <div className="gallery-item-container">
                            <img className='gallery-item' src={image.url} key={ images.id } />
                            <div className='remove-item' onClick={() => removeImage(image)}><span class="dashicons dashicons-trash"></span></div>
                            <div className='caption-text'>{image.caption[0]}</div>
                    </div>
                    )
                })

            )
        }

        //JSX to return
        return (
            <div>
                <div className="gallery-grid">
                    {displayImages(images)}
                </div>
                <br/>
                <MediaUpload
                        onSelect={(media) => {setAttributes({images: [...images, ...media]});}}
                        type="image"
                        multiple={true}
                        value={images}
                        render={({open}) => (
                            <Button className="select-images-button is-button is-default is-large" onClick={open}>
                                Add images
                            </Button>
                        )}
                    />
            </div>

        );
    },

    /**
     * The save function defines the way in which the different attributes should be combined
     * into the final markup, which is then serialized by Gutenberg into post_content.
     *
     * The "save" property must be specified and must be a valid function.
     *
     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
     */
    save({attributes}) {
        //Destructuring the images array attribute
        const { images = [] } = attributes;

        // Displays the images
        const displayImages = (images) => {
            return (
                images.map( (image,index) => {
                    return (
                            <img
                                className='gallery-item'
                                key={images.id}
                                src={image.url}
                                data-slide-no={index}
                                data-caption={image.caption[0]}
                                alt={image.alt}
                                />
                    )
                })
            )
        }

        //JSX to return
        return (
            <div>
            <div className="gallery-grid" data-total-slides={images.length}>{ displayImages(images) }</div>
            </div>
        );

    },
} );

Nach dem Hinzufügen von Styling sieht meine Galerie im Editor folgendermaßen aus:

enter image description here

7
Andreas