Gutenberg – Mehrere InnerBlocks in einem Blocktyp

Lesezeit: 7 Minuten

Benutzeravatar von Erik Kubica
Erik Kubica

Ich versuche, benutzerdefinierte Spalten zu blockieren, da der von Gutenberg verwendete WordPress-Standard nicht das ist, was ich brauche.

Also habe ich nachgeschlagen, wie es funktioniert, es verwendet InnerBlocks-Block mit einer Layout-Definition, aber es gibt keine Möglichkeit, das HTML-Tag und die Klasse für die Spalten anzugeben, also ist es für mich nutzlos.

Dann habe ich mich entschieden, Spalten mit map zu loopen, was gut funktioniert, dann habe ich in jeder Spalte die InnerBlocks-Komponente hinzugefügt, um das Einfügen anderer Blöcke in die Spalte zu ermöglichen, aber das Problem ist, dass in jeder Spalte der Inhalt von InnerBlocks geteilt wird, also ich Ich habe versucht, die Schlüsseleigenschaft für jeden InnerBlock und jede Spalte so festzulegen, dass sie eindeutig sind, und ihr Inhalt wird immer noch geteilt (nein, ich verwende keinen geteilten Block).

Es sieht so aus, als würde Gutenberg in jeder Spalte dieselbe Instanz von InnerBlocks verwenden.

Ich versuche, einen Blocktyp zu erstellen, bei dem Sie Spalten dynamisch hinzufügen und in jede Spalte “Karten” mit einigen Informationen einfügen können.

Um eine Vorstellung davon zu geben, was ich tue, hier ist die Rückgabe der Bearbeitungsfunktion:

<section className="infonav">
            <div className="infonav__container">
                <div>
                    <button onClick={onAddBox}>{__('Add column', 'zmg-blocks')}</button>
                </div>
                <div className="infonav__row">
                    {[...new Array(columns).keys()].map((item, index) => {
                        return (
                                <div className="infonav__row__col" key={"info_cols"+index}>
                                    <div>
                                        <button onClick={onRemoveBox.bind(index)}>
                                            {__('Remove', 'zmg-blocks')}
                                        </button>
                                    </div>
                                    <InnerBlocks key={"info_boxes"+index}/>
                                </div>
                        );
                    })}
                </div>
            </div>
        </section>

Vielen Dank

Benutzeravatar von Swopnil Dangol
Swopnil Dangol

Scheint so, als ob gutenberg Innerblocks nur einmal in einem Block verwendet werden können

Hinweis: Ein Block kann höchstens ein einzelnes InnerBlocks- und InnerBlocks.Content-Element beim Bearbeiten bzw. Speichern rendern. Um unterschiedliche Anordnungen von verschachtelten Blöcken zu erstellen, erstellen Sie einen separaten Blocktyp, der seine eigenen InnerBlocks rendert, und weisen Sie ihn als einzigen Typ „allowedBlocks“ zu.

Quelle: https://github.com/WordPress/gutenberg/tree/master/packages/block-editor/src/components/inner-blocks

Sie müssen einen weiteren benutzerdefinierten Block (nur für die Spalte) zusammen mit diesem Block erstellen, der auch Innerblock darin verwendet, damit andere Blöcke darin verschachtelt werden können. Sie können AllowedBlocks verwenden, um nur Ihre benutzerdefinierte Spalte in diesem Block zuzulassen

  • InnerBlocks ist jetzt Teil der block-editor Paket, nicht die editor Paket. Somit ist die richtige URL github.com/WordPress/gutenberg/tree/master/packages/…. Obwohl es nicht wirklich empfehlenswert ist, zu verlinken master URLs, da sie sich ändern können.

    – swissspidy

    12. März 2019 um 9:08 Uhr

  • Wie würden Sie diesen benutzerdefinierten Block in Ihren Hauptblock einfügen? Wenn Sie Ihre Erklärung veranschaulichen könnten, wäre das wirklich sehr hilfreich 🙂

    – Rodrigo D’Agostino

    18. Juni 2019 um 19:34 Uhr

Benutzeravatar von snnsnn
snnsnn

Wenn Sie mehrere Gutenberg-Blöcke über hinzufügen wollten InnerBlock aus dem ‘block-editor’, wie unten gezeigt, gibt es noch keine Möglichkeit, mehrere Blöcke hinzuzufügen:

const BLOCK_TEMPLATE = [
  ['image-slider', { width: 800, height: 400 }],
  ['menu'],
];

registerBlockType('peregrine/inner-block-demo', {

  title: 'Inner Block Demo',

  edit({ className }) {
    return (
      <div className={className}>
        <InnerBlocks
          template={BLOCK_TEMPLATE}
          templateLock="all"
        />
      </div>
    );
  },

  save() {
    return (
      <div>
        <InnerBlocks.Content />
      </div>
    );
  },
});

Mehrere innere Blöcke haben Komplexitäten, die den Aufwand nicht wert zu sein scheinen, und im Allgemeinen deutet es entweder auf einen Block hin, der in mehrere einfachere Blöcke zerlegt werden sollte, oder auf Blockattribute (nicht Kinder). Teilen Sie uns mit, wie der obige Vorschlag für Sie funktioniert, und wir könnten ihn erneut prüfen.

Hier können Sie die Diskussion verfolgen: https://github.com/WordPress/gutenberg/issues/6808

Aber Ihr Code sieht eher aus wie das Hinzufügen innerer Elemente, und das ist möglich.

Um dies weiter zu verdeutlichen, ist das, was Sie der Funktion registerBlockType zur Verfügung stellen, kein Block. Ein Gutenberg blockiert einen anmutigen Shortcode, etwa so:

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://stackoverflow.com/questions/51072386/source.jpg" alt="" /></figure>
<!-- /wp:image -->

Oder dieses:

<!-- wp:latest-posts {"postsToShow":4,"displayPostDate":true} /-->

Der erste wird statischer Block genannt, weil er seinen Inhalt enthält. Der zweite wird dynamischer Block genannt, weil er ein selbstschließender Block ist und keinen Inhalt hat. Der Inhalt wird von dem PHP-Callback abgerufen, den Sie bei der Registrierung Ihres Blocks angegeben haben.

Gutenberg verwendet React, um eine visuelle Darstellung des Blocks auf dem Editor-Bildschirm zu drucken. Die edit-Methode für das Einstellungsobjekt sollte ein React-Element zurückgeben, dieses Element wird verwendet, um eine visuelle Darstellung für den Block im Editor zu erzeugen. Die save-Methode sollte auch das React-Element zurückgeben, aber dieses Element wird in statisches HTML gerendert und in der Datenbank gespeichert: <figure class="wp-block-image"><img src="https://stackoverflow.com/questions/51072386/source.jpg" alt="" /></figure>. Jetzt haben dynamische Blöcke kein Rückgabeelement, da sie null zurückgeben, also enthalten sie keinen Inhalt, deshalb schließen sie sich selbst.

Wenn der Server auf eine Anfrage antwortet, erhält er den in der Datenbank gespeicherten Inhalt und führt ihn durch den Parser, um zu sehen, ob es sich um einen statischen oder dynamischen Block handelt. Wenn der Block statisch ist, hat er seinen Inhalt in sich selbst, sodass der Inhalt zurückgegeben wird. Wenn es dynamisch ist, wird eine registrierte Callback-Funktion aufgerufen und ihr Rückgabewert zurückgegeben.

Um Ihre Frage zu beantworten, sollten die Speicher- und Bearbeitungsfunktionen das Reaktionselement zurückgeben. Ein React-Element muss ein einzelnes Root-Element haben, aber innere Elemente können jedes normale HTML wie dieses sein:

<div>
  <h1>Hello world</h1>
  <p>This is a sentence</p>
</div>

Dies hat Performance-Gründe. DOM-Operationen sind teuer, deshalb hat es einen einzigen Einstiegspunkt in das DOM. Deshalb ist es sehr schnell. Es hat dann sein eigenes DOM, ein ganzer Baum befindet sich im Speicher. React geht durch seinen DOM-Baum, wenn eine Änderung stattfindet, und rendert nur den geänderten Zweig, malt nicht den ganzen Baum mit jeder kleinen Änderung.

Wichtiges Detail hier ist, dass der obige Code wie HTML aussieht, aber es ist nicht, es ist jsx. React kann HTML nicht direkt rendern. Jsx wird von einem Transpiler wie babel in das React-Element transpiliert.

Es gibt auch eine createElement-Methode auf React, die verwendet werden kann, um ein React-Element zu erstellen. wp exportiert diese Methode erneut.

Sie können ein Reaktionselement in einem anderen rendern. Ohne Lernreaktion können Sie die Kraft oder das Potenzial von Blöcken nie vollständig erfassen. Die Reaktionsbibliothek ist nicht so groß. Sobald Sie die Idee dahinter verstanden haben, können Sie es genug lernen, um in ein oder zwei Wochen produktiv zu sein.

  • Vielen Dank, sehr gut erklärt, ich bin mit React vertraut, das ich darin entwickle, aber in reinem React würde dieser Code ohne Probleme funktionieren (da ich viele Repeater- / Sammelformulare gemacht habe), aber jetzt habe ich das verstanden, falls Guttenberg React verwendet Ich muss eine separate Komponente für infoav__row__col erstellen

    – Erik Kubica

    30. Januar 2019 um 9:24 Uhr


Ich hatte das gleiche Problem und habe basierend auf Swopnil Dangols Antwort so etwas wie das Folgende erstellt:

Elternblock:

registerBlockType("my-plugin/parent-block", {

    title: "Parent block",

    // Amount of columns
    attributes: {
        columns: { type: "number", default: 3 },
    }

    edit(props) {
        const { attributes: { columns } } = props;

        const onChangeColumns = (newColumns) => {
            setAttributes({ columns: newColumns });
        };

        // Either go for the template route
        // (create an inner block template based on amount of columns)
        const template = Array.from(Array(columns).keys()).map((i) => [
            "my-plugin/custom-inner-block",
        ]);
      
        // Or go for the allowed blocks route
        const allowedBlocks = ["my-plugin/custom-inner-block"];

        return (
            <div {...useBlockProps()}>

                {/* Use RangeControl in the InspectorControls to 
                    control the number of columns. */}
                <InspectorControls key="setting">
                    <div class="block-editor-block-card">
                        <fieldset>
                            <legend className="blocks-base-control__label">
                                {__("Amount of columns", "gutenpride")}
                            </legend>
                            <RangeControl
                                label="Columns"
                                value={columns}
                                onChange={(value) => onChangeColumns(value)}
                                min={1}
                                max={3}
                            />
                        </fieldset>
                    </div>
                </InspectorControls>
    
                <InnerBlocks
                    template={activeTemplate}
                    templateLock="all"
                    allowedBlocks={allowedBlocks}
                />
            </div>
        )
    },

    save() {
        return (
            <div {...useBlockProps.save()}>
                <InnerBlocks.Content />
            </div>
        );
    },

    // ...
}

Benutzerdefinierter innerer Block:

registerBlockType("my-plugin/custom-inner-block", {

    title: "Custom Inner Block",

    edit(props) {
        const { attributes } = props;
        const { title } = attributes;

        return (
            <div {...useBlockProps()}>
                <InnerBlocks/>
            </div>
        );
    },

    save() {
        return (
            <div {...useBlockProps.save()}>
                <InnerBlocks.Content />
            </div>
        );
    },

    // ...
});

1393460cookie-checkGutenberg – Mehrere InnerBlocks in einem Blocktyp

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

Privacy policy