Gutenberg does not render changes in array of objects meta

Question

A post has a meta value which contains array of objects.

Seems like the values printed in a loop in fields do not render a changes unless I send a new meta key with dispatch.

This does not work, If i change the values in the fields printed in loop the values would not be rendered back to the fields and the changes typed will be ignored

LinksControl = withDispatch(
    (dispatch) => {
        return {
            handleLinksChange: (links, property, arrayIndex, value) => {
                links[arrayIndex][property] = value;
                links = links.slice(0);
                let meta = {meta: {links: links}}
                dispatch('core/editor').editPost(meta)
            }
        }
    }
)(LinksControl);

This works:

LinksControl = withDispatch(
    (dispatch) => {
        return {
            handleLinksChange: (links, property, arrayIndex, value) => {
                links[arrayIndex][property] = value;
                links = links.slice(0);
                let meta = {meta: {links: links,newKey:''}}
                dispatch('core/editor').editPost(meta)
            }
        }
    }
)(LinksControl);

Seems like the "newKey" somehow does render a change and the links array values do updated back the fields typed.

But when sending the "links" itself React/Gutenberg for some reason do not detect a change and do not render the values back to the fields.

I also noticed that in case 1 even without adding a "newKey" to meta object, if I start typing in a diffrent regular field with regular flat meta (not array) then the array fields values will render and update on change.

What is the correct way to fix this issue?

Adding the "newKey" feels like a hack and I’m looking for the correct way to render the values on change.

Full code snippet for reference:

import {registerPlugin} from 'wordpress user/plugins';
import {PluginDocumentSettingPanel} from 'wordpress user/edit-post';

const {RadioControl, TextControl, SelectControl} = wp.components
const {withSelect, withDispatch} = wp.data

let LinksControl = ({links, handleLinksChange}) => {
    return <div><h2>Links</h2>
        {links.map((link, arrayIndex) => (
            <div><h6>Link {arrayIndex + 1}:</h6>
                <TextControl
                    label="Set url"
                    value={links[arrayIndex].url}
                    onChange={link => handleLinksChange(links, 'url', arrayIndex, link)}
                />
                <SelectControl
                    label="Set Index"
                    value={links[arrayIndex].index}
                    onChange={(linkIndex) => {
                        handleLinksChange(links, 'index', arrayIndex, linkIndex)
                    }}
                    options={getRangeArray(1, 10)}
                />
            </div>
        ))
        }
    </div>
};

LinksControl = withSelect(
    (select) => {
        return {
            links: select('core/editor').getEditedPostAttribute('meta')['links']
        }
    }
)(LinksControl);

LinksControl = withDispatch(
    (dispatch) => {
        return {
            handleLinksChange: (links, property, arrayIndex, value) => {
                links[arrayIndex][property] = value;
                links = links.slice(0);
                let meta = {meta: {links: links}}
                dispatch('core/editor').editPost(meta)
            }
        }
    }
)(LinksControl);

const getRangeArray = (min, max) => {
    const arr = [];

    for (let i = min; i <= max; i++) {
        arr.push(i);
    }

    return arr.map(rank => {
        return {label: rank, value: rank}
    })
}

const CustomFieldsPanel = () => {
    
    return <PluginDocumentSettingPanel
        name="custom-panel"
        title="Custom fields"
        className="custom-panel"
    >
        <LinksControl/>
    </PluginDocumentSettingPanel>

};

registerPlugin('plugin-document-setting-panel-demo', {
    render: CustomFieldsPanel
})

0
BenB 2 years 2020-12-27T16:10:32-05:00 0 Answers 4 views 0

Leave an answer

Browse
Browse