4

I'm creating a block similar to the WP Core Table block, which first presents the user with a form to set the number of rows and columns. I'd like to set a default value in the TextControl for the number of columns.

Here's a highly simplified version of the block:

const { registerBlockType } = wp.blocks; 
var el = wp.element.createElement;
const { TextControl } = wp.components;

registerBlockType( 'cgb/a11ytable', {
    title: 'Accessible Table',
    icon: 'screenoptions',
    category: 'common',
    attributes: {
        numCols: {
            type: 'number'
        }
    },
    edit: (props) => {
        const { attributes: { numCols }, className, setAttributes } = props;
        return [
            el(
                TextControl, {
                    label: 'Number of Columns',
                    type: 'number',
////////////////////////////////////////////////////
                    value: 2, // this is the problem line
////////////////////////////////////////////////////
                    onChange: function(value) {
                        props.setAttributes({ numCols: value })
                    }
                }
            ),
        ];
    },
    save: ( props ) => {
        var attributes = props.attributes;
        return el('table', { className: props.classes },
            attributes.numCols
        );
    },
} );

The problem is, when the value of the TextControl is set to anything, as above (even when it is changed from just plain 2 to "2"), once the block is added in the editor, it's not possible to change the value. The up and down arrows which appear because it's type:number don't allow the number to change, and typing inside the input is disabled (you get a cursor, but can't select, add, or delete the 2).

The Gutenberg Handbook doesn't seem to go over syntax to set a default value. I don't think it needs a state, as this input just sends data to another function that creates the table itself and saves the value to an attribute for later calculations, it's not something the user can continue to manipulate.

1

Try setting the default value in your attributes instead of on the TextControl.

registerBlockType( 'cgb/a11ytable', {
    title: 'Accessible Table',
    icon: 'screenoptions',
    category: 'common',
    attributes: {
        numCols: {
            type: 'number',
            default: 2 // Added default value 
        }
    },
    edit: (props) => {
        const { attributes: { numCols }, className, setAttributes } = props;
        return [
            el(
                TextControl, {
                    label: 'Number of Columns',
                    type: 'number',
////////////////////////////////////////////////////
                    value: props.attributes.numCols, // this is the problem line
////////////////////////////////////////////////////
                    onChange: function(value) {
                        props.setAttributes({ numCols: value })
                    }
                }
            ),
        ];
    },
    save: ( props ) => {
        var attributes = props.attributes;
        return el('table', { className: props.classes },
            attributes.numCols
        );
    },
} );
  • That does add a default for later, but I'm wanting the default to actually appear in the input. That way if the user adds the block, they can immediately submit the form and add the table. My actual textcontrol has "required" set, so currently if the user adds the block and tries to submit the form, they get a validation error and have to enter a number in the input. – WebElaine Apr 23 at 20:59
  • 1
    After some more testing on my end I am wondering if its a bug? I have the exact setup with a RangeControl and the initial value is set correctly. I changed it to a TextControl type=number and I get the same results as you (uneditable, errors in console). You might want to post something for the Gutenberg dev team. In the meantime, I would suggest using RangeControl, it works and actually makes more sense since you can set a min and max value, I'm sure you don't want to handle a table with 100 columns :) – RiddleMeThis Apr 23 at 21:36
  • I don't know what changed, but I tried setting the default the same way you had it, and it worked this time, even though I thought I had it just like this before. I'll play around with the RangeControl too - thanks, I hadn't seen it before. I think I like the UI of a textcontrol better than the slider there, though - you can set min and max as attributes and get built-in html5 validation, so I can still cap the max number of columns. No, I definitely do not want any insane tables. :) – WebElaine Apr 23 at 21:42
  • I have a TextControl working as well now :) Seems very sensitive to what and how you pass it. There is a lot of playing around with this stuff until the docs improve. – RiddleMeThis Apr 23 at 21:56
  • 1
    @WebElaine, "I'm wanting the default to actually appear in the input" - actually, that's pretty easy. Just use value: numCols || 2 (short version of value: numCols ? numCols : 2) - tried and tested working. :) – Sally CJ Apr 24 at 1:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.