Search code examples
reactjswordpresswordpress-gutenberg

Saving Tags applied programmatically in Gutenberg


I've implemented a routine to programmatically apply tags / categories to a post within Gutenberg. The code for this can be seen in my most recent question at: https://stackoverflow.com/a/70029499/40593 and is also presented below:

//Add Tag & Category in one call
function AddTaxonomies(tag, category){
    AddTag(tag);
    AddCategory(category);
}

//Add Tag & Refresh Panel
function AddTag(tag){

    //Get Current Selected Tags
    let tags = select( 'core/editor' ).getEditedPostAttribute( 'tags' );

    //Get State of Tag Panel
    let is_tag_panel_open = select( 'core/edit-post' ).isEditorPanelOpened( 'taxonomy-panel-tags' );

    //Verify new tag isn't already selected
    if(! tags.includes(tag)){

        //Add new tag to existing list
        tags.push(tag);

        //Update Post with new tags
        dispatch( 'core/editor' ).editPost( { 'tags': tags } );

        // Verify if the tag panel is open
        if ( is_tag_panel_open ) {

            // Close and re-open the tag panel to reload data / refresh the UI
            dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-tags' );
            dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-tags' );
        }            
    }

}

//Add Category & Refresh Panel
function AddCategory(category){

    //Get Current Selected Categories
    let categories = select( 'core/editor' ).getEditedPostAttribute( 'categories' );

    //Get State of Category Panel
    let is_category_panel_open = select( 'core/edit-post' ).isEditorPanelOpened( 'taxonomy-panel-category' );

    //Verify new category isn't already selected
    if(! categories.includes(category)){

        //Add new tag to existing list
        categories.push(category);

        //Update Post with new tags
        dispatch( 'core/editor' ).editPost( { 'categories': categories } );

        // Verify if the category panel is open
        if ( is_category_panel_open ) {

            // Close and re-open the category panel to reload data / refresh the UI
            dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-category' );
            dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-category' );
        }            
    }
}

This code will apply a tag / category to a post in Gutenberg (also updating the UI to reflect this) and can be verified as having updated the redux store for the post using:

wp.data.select( 'core/editor' ).getEditedPostAttribute( 'tags' )

However, I've noticed two issues:

  1. Firstly, simply updating the tags / categories in this way doesn't trigger the "Update" button for the post to become active. To work around this I have to update a private metafield then it will become active.
  2. If having worked around this issue by updating a private meta field, then having clicked Update for the post. The UI is reloaded but the new tags / categories are not saved, and subsequently cleared from the UI.

Any advice?


Solution

  • With thanks to @harisrozak over on the gutenberg github repo, the following solution was identified.

    Notably, I believe that because I was using the same array for reading the selected tags / categories, as I was for then updating them, React / Redux wasn't seeing that data as having changed and so didnt actually update the database properly (despite both the UI and the redux store updating).

        //Add Category & Refresh Panel
        function AddCategory(category){
    
            //Get Current Selected Categories
            let categories = select( 'core/editor' ).getEditedPostAttribute( 'categories' );
    
            //Verify new category isn't already selected
            if(! categories.includes(category)){
    
                //Create new array for updating selected categories
                var new_categories = [category];
    
                //Add categories already selected into new array
                for (let i = 0; i < categories.length; i++) {
    
                    //Get current category
                    const selected_id = categories[i];
    
                    //Check category isnt included already
                    if ( ! new_categories.includes( selected_id ) ) {
                        new_categories.push(selected_id);
                    }
                } 
    
                //Update Post with new categories
                updateState(() => dispatch( 'core/editor' ).editPost( { 'categories': new_categories } ));
    
                //Get State of Category Panel
                let is_category_panel_open = select( 'core/edit-post' ).isEditorPanelOpened( 'taxonomy-panel-category' );            
    
                // Verify if the category panel is open
                if ( is_category_panel_open ) {
    
                    // Close and re-open the category panel to reload data / refresh the UI
                    dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-category' );
                    dispatch( 'core/edit-post' ).toggleEditorPanelOpened( 'taxonomy-panel-category' );
                }        
            }
        }
    

    Ref: Gist provided by @harisrozak