The saving feature of WP Blocks does not correspond with the editing feature upon loading the editor

I am currently in the process of developing a WP Gutenberg block that is based on https://github.com/JimSchofield/Guty-Blocks-2. However, I have encountered an issue where the saved content does not match the editor when loaded, resulting in an error message stating 'This block contains unexpected or invalid content'.

Despite my attempts to investigate the problem in the browser console, I have been unable to pinpoint the source of the discrepancy. Both the editing and saving functions reference the images, but they are not being stored by the save function.

It is important to note that once the block is initially loaded, used, and the post is saved, it functions correctly on the front-end. The issue arises when returning to the editor.

import './__block__.view.scss';
import './__block__.editor.scss';

const {
    registerBlockType,
    getBlockDefaultClassName
} = wp.blocks;

const { 
    InspectorControls,
    MediaUpload
} = wp.editor;

const {
    Button
} = wp.components;

registerBlockType('__namespace__/__block__', {
    title: '__prettyname__(noCase)',
    icon: '__icon__',
    category: '__category__',

    attributes: {
        imgUrl: {
            type: 'array',
            source: 'children',
            selector: 'img',
        },
    },

    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>
                <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>
                    )}
                />
                <br />
                <div class="modal__img">
                    <div class="flexslider">
                        <ul class="slides" data-total-slides={images.length}>{ displayImages(images) }</ul>
                    </div>
                </div>
            </div>
        );
    },

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

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

        //JSX to return
        return (
            <div class="modal__img">
                <div class="flexslider">
                    <ul class="slides" data-total-slides={images.length}>{ displayImages(images) }</ul>
                </div>
            </div>
        );

    },
});

Upon entering the editor, I expected the block to output the original HTML, but this behavior does not seem to be working as intended.

Answer №1

When working with both the save and edit functions, you are pulling images from the attributes prop. However, upon registering your block and setting up the attributes, only imageUrl is specified as an attribute. This results in images not being stored in the database and being unavailable for editing later on.

The solution lies in adding images as an attribute.

Here's the current setup:

attributes: {
    imgUrl: {
        type: 'array',
        source: 'children',
        selector: 'img',
    },
},

Instead, it should be:

attributes: {
    images: {
        type: 'array',
        default: []
    },
},

Answer №2

If you want to improve your code, consider using props instead of attributes when working with edit and save functions. You can easily access the attributes by using:

var attributes = props.attributes;

To learn more, explore the sample code provided in these examples.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to creating animations with javascript/react js

My attempt at altering the opacity of an element every 100 milliseconds following a click event has not been successful. The function change is triggered by a click, yet the code does not work as intended. Here's what I have so far: function change (i ...

Tips on establishing validators for deeply nested form controls within form groups in Angular 6 reactive forms

In my form array (experiencesArray), I have nested nested nested form controls (companyname), as shown below. this.personalFormGroup = this._formBuilder.group({ professionalInfo: this._formBuilder.group({ totalexpyears: ['', Validators.req ...

Using Selenium together with Mocha/Chai to determine the absence of an item in the DOM and return false

In my current project, I am using selenium-webdriver with Mocha & Chai in a JavaScript environment. I am trying to determine if a user is logged in by checking for the presence of a specific element in the DOM. If the user is logged in, then the following ...

What is the use of the typeof operator for arrays of objects in TypeScript?

How can I update the any with the shape of the options's object below? interface selectComponentProps { options: { label: string; value: string; }[]; } const SelectComponent: React.FC<selectComponentProps> = ({ options, }) => ...

Challenges with JavaScript and JQuery - Extracting and Displaying YouTube Information on Website

While I have some experience with Javascript and JQuery, my latest project on FirstPersonTheater.net is not going as planned. I am using PHP to generate a video ID in javascript code to retrieve information about YouTube videos such as title, uploader, vie ...

Error encountered: Index 109 - The function $.ajax(...).success is not recognized as a valid function while working with jQuery in a Node

I'm just starting to learn about jquery and have been experimenting with ajax in my recent code. Below is the snippet of what I have implemented: $(function(){ $("#status").change(function(){ if($(this).is(':checked')) ...

Preventing access to websites on mobile devices: A step-by-step guide

Ensure an error page is shown when the website is accessed on a mobile device. I've attempted the following: @media only screen (max-device-width : 768px) { html,body { display: none; } } as well as: if( /Android|webOS|iPhone|iPad|iPod|BlackB ...

Struggling to display text content from an array onto the HTML webpage

One issue I am encountering is my inability to use Javascript to change the text within an HTML p tag. I have an HTML button with the id="knap" and a p tag with the id="answer". My goal is to change the text in the "answer" tag when the user clicks on the ...

Control the line height in DataTables

Is there a way to adjust the line height for a tr using either DataTables settings or CSS? I've attempted different methods, but nothing seems to change the line-height. https://i.sstatic.net/GwFaD.png Table CSS ...

Exploring Multilingual Autocomplete or: Best Practices for Managing Multiple Languages in Web Applications

I'm currently developing a website and I have a mysql-table named 'items' with the following structure: item_id | item (The second column is used to identify the item_id.) In a file called language1.php, I have an array that stores the it ...

What causes the `super` keyword property to return undefined within an ES6 class?

As a newcomer to ES6 classes, I am exploring how inheritance functions within it. To experiment with this concept, I have constructed a parent class named Modal and a child class called ChildModal. Below is the content of these classes: class Modal { ...

Problem with finding Rails controller file in .coffee extension

I recently started learning Rails and came across a file called welcome.js.coffee in the assets javascripts directory. # Place all the behaviors and hooks related to the matching controller here. # All this logic will automatically be available in applica ...

Discovering ways to align specific attributes of objects or target specific components within arrays

I am trying to compare objects with specific properties or arrays with certain elements using the following code snippet: However, I encountered a compilation error. Can anyone help me troubleshoot this issue? type Pos = [number, number] type STAR = &quo ...

Make TextField with type number forcibly show dot as decimal separator

I am currently utilizing the material-ui library to display a TextField component in my react application. Strangely, all instances of <TextField type="number /> are displaying decimal separators as commas (,) instead of dots (.), causing confusion f ...

Fill a .js script with moustache.js

I need help with organizing some JavaScript code that needs to access server-side data. I want to keep this code in a separate .js file, but I'm having issues populating it with the necessary server information using moustache. Here is my current setu ...

When the button is clicked, Ajax fails to abort

Is there a way to cancel an ajax request when a button is clicked? I've tried some solutions I came across here, but none seem to work for me. <button type="button" id="toStop">Stop</button> Despite clicking the stop b ...

The Node gracefully disconnects and apologizes: "I'm sorry, but I can't set headers after they have already

events.js:160 throw er; // Unhandled 'error' event ^ Error: Can't set headers after they are sent. register.js:20:18 register.js user.save(function(err) { if(err){ return mainFunctions.sendError(res, req, err, 500, ...

Is it possible to verify that a string exclusively comprises elements from an array?

Hey there, I've got a challenge where I need to verify whether a string consists only of letters from a predefined alphabet. If not, my bot kicks players from the game. I've come up with the following script: var letters = "a b c d e f g ...

Load specific options only when needed while maintaining the previously selected state

First off, check out this demo to see what I mean. I have a basic form with a dropdown field. Initially, only one option is pre-loaded and selected. The goal is to load the remaining options when the dropdown is clicked. This functionality works fine, exc ...

Wondering how to initiate an AJAX API function within a Windows application?

Recently, a company has provided me with a web-based API to access their services. Utilizing this API within a web browser hasn't posed any issues for me: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="text/javascri ...