Gibt es eine Möglichkeit, die Kategorieliste zu aktualisieren, die in einer benutzerdefinierten Komponente verwendet wird, wenn ein Benutzer eine neue Kategorie mit dem Editor selbst hinzufügt?

Lesezeit: 5 Minuten

Ich habe eine benutzerdefinierte Komponente für den Gutenberg-Editor von WordPress erstellt. Ich brauchte eine Möglichkeit, eine einzelne Kategorie aus einer Liste bereits ausgewählter Kategorien auszuwählen. Ich konnte diese Art von Funktionalität mit dem folgenden Code erreichen. Das einzige Problem mit meiner Komponente ist, dass sie ihre Kategorieliste nicht aktualisiert, wenn der Benutzer eine völlig neue Kategorie hinzufügt, während er sich im Editor selbst befindet. Beim Hinzufügen einer solchen Kategorie wird die Kategorie automatisch ausgewählt und sollte daher in der benutzerdefinierten Dropdown-Liste vorhanden sein .

Ich habe die Dokumentation durchgesehen und finde keinen Weg, diesen Effekt zu erzielen, wie es scheint select().getEntityRecords() speichert den ersten Ergebnissatz, den es erhält, und fragt ohne eine Seitenaktualisierung nicht nach neuen Daten ab.

Nebenbemerkung: Es gibt zusätzliche Funktionen, um die Anzahl der regulären Kategorien zu begrenzen, die ein Benutzer überprüfen kann. Derzeit begrenzt mein Code es auf 3 und erlaubt dem Benutzer nicht, den Beitrag zu speichern, wenn er mehr als 3 überprüft hat.

index.js

// WordPress dependencies.
import { createElement as el, Fragment } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

// Internal dependencies.
import PostPrimaryCategory from './post-primary-category';
/**
 * Add new field to category content block
 * Also add a limit check for categories
 * 
 * @param {*} OriginalComponent 
 */
function wrapPostPrimaryCategory( OriginalComponent ) {
    return function( props ) { 
    // create content block 
    let originalElement = el( OriginalComponent, props );
    let errorMessage    = null;
    // if the content block is category
    if ( 'category' === originalElement.props.slug ) {      
      // turn on update/publish button
      jQuery( ".editor-post-publish-button" ).prop( "disabled", false );
      if ( 3 < originalElement.props.terms.length ) {
        // if number of categories is more then 3, show error and disable publish/edit button
        errorMessage = el( 'p', { class: 'error-message' }, __( 'Too many categories have been selected', 'post-categories-error' ) );
        jQuery( ".editor-post-publish-button" ).prop( "disabled", true );
      }
    }

    // compile all elements of the content block together
    let elements="category" !== originalElement.props.slug ? el(
      Fragment, null,
      originalElement
    ) : (
      el(
        Fragment, null,        
        el( 'h4', null, __( 'Categories', 'post-categories' ) ),
        // show error message if there is one
        errorMessage,
        originalElement,    
        // Show a custom heading
        el( 'h4', null, __( 'Primary Category', 'post-primary-category' ) ),
        // add new field
        <PostPrimaryCategory selectedTerms={ originalElement.props.terms } />    
      )
    );

    return elements;
    };
}
// hook to get access to the category ( and post tags ) content blocks in the editor
wp.hooks.addFilter(
    'editor.PostTaxonomyType',
    'authentic-child/assets/js/post-primary-category',
    wrapPostPrimaryCategory
);

post-primary-category.js

// WordPress dependencies.
import { SelectControl } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';

// Whenever the post is edited, this would be called. And we use it to pass the
// updated metadata to the above function.
const applyWithSelect = withSelect( ( select ) => {
    return {
        primaryCategory: select( 'core/editor' ).getEditedPostAttribute( 'meta' ).primary_category,
        categories: select( 'core' ).getEntityRecords( 'taxonomy', 'category', { per_page:-1, hide_empty:false } )
    };  
} );

// Whenever the post is edited, this would also be called. And we use it to update
// the metadata through the above function. But note that the changes would only
// be saved in the database when you click on the submit button, e.g. the "Update"
// button on the post editing screen. :)
const applyWithDispatch = withDispatch( ( dispatch ) => {
    const { editPost } = dispatch( 'core/editor' );
    return {
        onSetPrimaryCategory( primaryCategory ) {
            const meta = { primary_category: primaryCategory };
            editPost( { meta } );
        }
    };
} );

// This basically simply renders the select drop down.
function PostPrimaryCategory( {
    // passsed in from the wrap function in index.js
    selectedTerms,
    // These these props are passed by applyWithSelect().
    primaryCategory,
    categories,
    // Whereas this is passed by applyWithDispatch().
    onSetPrimaryCategory,
} ) {
    return (
        <>
            <SelectControl
                label="This category will be displayed on the post when it is on the home/search pages"
        value={ primaryCategory }
        onChange={ onSetPrimaryCategory }
        options={ null === categories || undefined === categories ? [] : 
          categories
            .filter( ( { id, name } ) => ( "Uncategorized" === name || -1 === selectedTerms.indexOf( id ) ? false : true ) )
            .map( ( { id, name } ) => ( { label: name, value: name } ) ) }
            />
        </>
    );
}

// And finally, 'compose' the above functions.
export default compose( applyWithSelect, applyWithDispatch )( PostPrimaryCategory );

  • Ich verstehe nicht. Wie fügen Benutzer eine neue Kategorie hinzu? Select-Control hat diese Option nicht. können Sie einen Code aus diesem Teil teilen? oder Bild

    – Armin Yahya

    7. Dezember 2020 um 16:07 Uhr

  • @arminyahya Nein, das ist eine eingebaute Funktionalität von WordPress selbst. WordPress ermöglicht es dem Benutzer, neue Kategorien und die meisten anderen Taxonomien im Zusammenhang mit Beiträgen spontan hinzuzufügen, wenn er einen Beitrag im Editor bearbeitet/erstellt. Ich habe also keine einfache Möglichkeit, den Code zu teilen, der das steuert. Es tut uns leid.

    – Josh Balcitis

    7. Dezember 2020 um 17:03 Uhr

Du kannst den … benutzen useSelect benutzerdefinierter React-Hook innerhalb einer Funktionskomponente. useSelect wird Änderungen “abonnieren” und die Komponente automatisch neu rendern, wenn sich die Werte ändern (dh der Benutzer wählt eine andere Kategorie aus).

Die zu erstellende Komponente a <SelectControl> das den Benutzer eine “Primärkategorie” auswählen lässt, könnte etwa so aussehen:

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { SelectControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

function PostPrimaryCategory() {
    const categories = useSelect((select) => {
        /**
         * Get the currently selected categories for a post. Since we are using 
         * useSelect, this will get updated any time the user adds or removes a 
         * category from the post.
         */
        const catIds = select('core/editor').getEditedPostAttribute('categories');

        /**
         * The line of code above just gets us an array of category IDs, so here
         * we get the full category details (name, slug, id, etc) that we can
         * use to populate the SelectControl.
         */
        return !!catIds && catIds.length > 0 ?
            select('core').getEntityRecords('taxonomy', 'category', {
                include: catIds.join(','),
                per_page: -1,
            }) : [];
    });

    // We need the post type for setting post meta
    const postType = useSelect((select) => {
        return select('core/editor').getCurrentPostType();
    });

    // Get and set the post meta
    const [meta, setMeta] = useEntityProp('postType', postType, 'meta');

    return (
        <SelectControl
            label={ __('Primary Category', 'text-domain') }
            value={ meta.primary_category }
            options={ categories.map(cat => {
                return {
                    label: cat.name,
                    value: cat.id,
                }
            }) }
            onChange={ (value) => setMeta({primary_category: value}) }
        />
    );
};

1385750cookie-checkGibt es eine Möglichkeit, die Kategorieliste zu aktualisieren, die in einer benutzerdefinierten Komponente verwendet wird, wenn ein Benutzer eine neue Kategorie mit dem Editor selbst hinzufügt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy