Attivare Javascript al salvataggio in Gutenberg (Block Editor)

13 nov 2018, 03:01:39
Visualizzazioni: 15.2K
Voti: 16

Ho un metabox a cui vorrei attivare del Javascript quando un post viene salvato (per ricaricare la pagina in questo caso d'uso).

Nell'editor classico, questo può essere fatto tramite un semplice reindirizzamento agganciato a save_post (con una priorità alta)

Ma dato che Gutenberg converte il processo di salvataggio per i metabox esistenti in chiamate AJAX individuali ora, deve essere fatto in javascript, quindi come posso:

  • Ascoltare un evento in cui tutti i processi di salvataggio sono completati e poi attivare il javascript? Se sì, come si chiama questo evento? Esiste una referenza per questi eventi da qualche parte? OPPURE

  • Attivare javascript all'interno del processo di salvataggio AJAX del metabox, che può poi controllare lo stato del processo di salvataggio della pagina genitore prima di continuare?

7
Commenti

Far riavviare solo il tuo metabox in Gutenberg è anche una potenziale soluzione, così come implementare l'interfaccia utente del metabox in JS e basarsi sugli store di dati wp.data

Tom J Nowell Tom J Nowell
13 nov 2018 04:07:41

@TomJNowell Ho trovato questo riferimento che posso usare per verificare alcuni stati, ma non sono sicuro come accedervi: https://wordpress.org/gutenberg/handbook/data/data-core-editor/

majick majick
13 nov 2018 04:37:45

finora ho: ad es. wp.data.select('core/editor').isSavingPost() ... questo tipo di accesso non è documentato da nessuna parte che io veda... e sembra anche inaffidabile poiché restituisce false dopo che il post è stato salvato la prima volta (prima di ciò è undefined) indipendentemente dal fatto che l'editor stia ancora salvando o meno. facepalm

majick majick
13 nov 2018 07:50:11

Puoi anche segnalare un problema sul repository di Gutenberg per supporto, è in tema qui ma potresti ottenere risposte da persone più competenti lì. Inoltre il sistema di hook JS di WP potrebbe essere una possibilità ma è solo un'ipotesi

Tom J Nowell Tom J Nowell
13 nov 2018 09:02:13

Pazzesco, qualcosa di semplice come questo è già stato richiesto e non è supportato: https://github.com/WordPress/gutenberg/issues/10044 ... ecco perché sto cercando un modo per farlo da solo.

majick majick
13 nov 2018 09:14:42

Quindi con ulteriori test isSavingPost in realtà sembra funzionare nel codice (vedi risposta) ma quando vi si accede dalla console del browser sembra sempre restituire false erroneamente. Pazienza.

majick majick
13 nov 2018 10:12:27

Arrivo piuttosto tardi, ma ho scritto un hook che può essere utilizzato per rilevare quando il processo di salvataggio lato server è completato. Puoi trovare l'hook qui - https://thewpvoyage.com/how-to-detect-when-a-post-is-done-saving-in-wordpress-gutenberg/

Siddharth Thevaril Siddharth Thevaril
21 ago 2024 13:22:07
Mostra i restanti 2 commenti
Tutte le risposte alla domanda 6
6
16

Non sono sicuro se esiste un modo migliore, ma sto ascoltando subscribe invece di aggiungere un event listener al pulsante:

wp.data.subscribe(function () {
  var isSavingPost = wp.data.select('core/editor').isSavingPost();
  var isAutosavingPost = wp.data.select('core/editor').isAutosavingPost();

  if (isSavingPost && !isAutosavingPost) {
    // Qui va il tuo codice AJAX ......

  }
})

Documentazione ufficiale dei dati dell'Editor di Post: https://wordpress.org/gutenberg/handbook/designers-developers/developers/data/data-core-editor/

11 mar 2019 14:11:42
Commenti

sembra molto più pulito, sono solo curioso di sapere da dove viene il metodo subscribe? fa parte della funzione wp.data? Non lo vedo menzionato nella documentazione.

majick majick
12 mar 2019 15:50:33

Sì, subscribe è un metodo del modulo wp.data. Apri la console quando modifichi un post con Gutenberg ed esegui wp.data. Questo elenca tutti i metodi disponibili del modulo dati.

tomyam tomyam
13 mar 2019 10:37:07

ottimo lavoro nel trovarlo! è un peccato che la documentazione di Gutenberg sia organizzata in modo così oscuro e non abbia abbastanza esempi. Inoltre, l'aspettativa che gli sviluppatori conoscano e/o vogliano imparare i metodi React è davvero eccessiva... Sono sicuro che possa essere un grande risparmio di tempo se li conosci già, ma è una vera perdita di tempo se non li conosci - mi ci sono volute ore solo per capire come accedere a qualcosa di utile nel modello wp.data. Per me si torna a PHP (e all'editor classico).

majick majick
14 mar 2019 11:30:55

Grazie per aver condiviso questo! Come posso intercettare e interrompere l'aggiornamento/pubblicazione del post in base a una condizione.

Mohammed AlBanna Mohammed AlBanna
12 dic 2019 03:27:39

Sembra che questo metodo attivi anche il codice quando un utente clicca sul pulsante "Sposta nel cestino" (lo stato del post cambia in "trash" e il valore isSavingPost è "true" indipendentemente da ciò). Inoltre, un singolo clic su "Aggiorna" ha attivato il codice di sottoscrizione 3 volte nel mio caso. Alla fine ho optato per ascoltare i clic su .editor-post-publish-button, .editor-post-save-draft e .editor-post-preview.

Oksana Romaniv Oksana Romaniv
6 mar 2020 15:57:26

Questo snippet è ottimo ma verrà attivato più volte, il seguente thread spiega come evitare che ciò accada: https://github.com/WordPress/gutenberg/issues/5975#issuecomment-483488988

csalmeida csalmeida
21 feb 2021 19:46:06
Mostra i restanti 1 commenti
1

Ok, quindi una soluzione molto più "hacky" di quanto volessi, ma alla fine funziona...

Ecco un modo leggermente semplificato e astratto per farlo dal mio codice, nel caso qualcuno avesse bisogno di fare la stessa cosa (sono sicuro che altri plugin lo faranno nel prossimo futuro.)

    var reload_check = false; var publish_button_click = false;
    jQuery(document).ready(function($) {
        add_publish_button_click = setInterval(function() {
            $publish_button = jQuery('.edit-post-header__settings .editor-post-publish-button');
            if ($publish_button && !publish_button_click) {
                publish_button_click = true;
                $publish_button.on('click', function() {
                    var reloader = setInterval(function() {
                        if (reload_check) {return;} else {reload_check = true;}
                        postsaving = wp.data.select('core/editor').isSavingPost();
                        autosaving = wp.data.select('core/editor').isAutosavingPost();
                        success = wp.data.select('core/editor').didPostSaveRequestSucceed();
                        console.log('Salvataggio in corso: '+postsaving+' - Autosalvataggio: '+autosaving+' - Successo: '+success);
                        if (postsaving || autosaving || !success) {classic_reload_check = false; return;}
                        clearInterval(reloader);

                        value = document.getElementById('metabox_input_id').value;
                        if (value == 'trigger_value') {
                            if (confirm('È necessario ricaricare la pagina. Ricaricare ora?')) {
                                window.location.href = window.location.href+'&refreshed=1';
                            }
                        }
                    }, 1000);
                });
            }
        }, 500);
    });

...basta cambiare metabox_input_id e trigger_value in base alle proprie esigenze. :-)

13 nov 2018 10:04:12
Commenti

È stato utile, l'unico esempio di riferimento che ho trovato per accedere alla gerarchia dei moduli JavaScript di Gutenberg: https://github.com/front/gutenberg-js

majick majick
13 nov 2018 10:18:26
0

Se qualcuno è ancora interessato, ho trovato un modo semplice per eseguire qualcosa subito DOPO che l'editor a blocchi (Gutenberg) completa la pubblicazione/aggiornamento di un articolo:

const editor = window.wp.data.dispatch('core/editor')
const savePost = editor.savePost

editor.savePost = function (options) {
    options = options || {}

    return savePost(options)
        .then(() => {
            // Fai qualcosa dopo che l'articolo è stato effettivamente salvato in modo asincrono.
            console.log('L\'articolo è stato salvato.')

            if (!options.isAutosave) {
               // Questo non è un salvataggio automatico.
            }
        })
}

In sostanza, lo snippet sopra sovrascrive la funzione nativa savePost().
Quindi la si sovrascrive con una propria funzione, si richiama savePost() al suo interno e si sfrutta la promise restituita semplicemente utilizzando then.

27 gen 2023 22:48:36
1

Per attivare l'azione (in questo caso una richiesta Ajax) DOPO che il salvataggio del post è COMPLETATO, puoi utilizzare un intervallo per attendere finché isSavingPost non restituisce nuovamente false.

let intervalCheckPostIsSaved;
let ajaxRequest;

wp.data.subscribe(function () {
    let editor = wp.data.select('core/editor');

    if (editor.isSavingPost()
         && !editor.isAutosavingPost()
         && editor.didPostSaveRequestSucceed()) {

        if (!intervalCheckPostIsSaved) {
            intervalCheckPostIsSaved = setInterval(function () {
                if (!wp.data.select('core/editor').isSavingPost()) {
                    if (ajaxRequest) {
                        ajaxRequest.abort();
                    }

                    ajaxRequest = $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {},
                        success: function (data) {
                            ajaxRequest = null;
                        }
                    });

                    clearInterval(intervalCheckPostIsSaved);
                    intervalCheckPostIsSaved = null;
                }
            }, 800);
        }
    }
});
15 giu 2021 03:32:52
Commenti

Decisamente la strada giusta - funziona alla perfezione. Ottimo lavoro!

Spencer Bigum Spencer Bigum
6 dic 2021 19:27:29
2

È necessario raccogliere la funzione unsubscribe dalla sottoscrizione e chiamarla per evitare chiamate multiple.

const unsubscribe = wp.data.subscribe(function () {
            let select = wp.data.select('core/editor');
            var isSavingPost = select.isSavingPost();
            var isAutosavingPost = select.isAutosavingPost();
            var didPostSaveRequestSucceed = select.didPostSaveRequestSucceed();
            if (isSavingPost && !isAutosavingPost && didPostSaveRequestSucceed) {
                console.log("isSavingPost && !isAutosavingPost && didPostSaveRequestSucceed");
                unsubscribe();


                // il tuo AJAX QUI();

            }
        });
13 apr 2020 14:14:19
Commenti

Sembra funzionare bene, tranne per il fatto che viene ancora attivato PRIMA del salvataggio completo del post. Il mio codice inserito sotto "unsubscribe()" viene eseguito prima che WordPress avvii il salvataggio del post via AJAX. Esiste una soluzione per eseguire il codice solo dopo che WordPress ha completato al 100% il salvataggio/aggiornamento del post?

Neoweiter Neoweiter
1 giu 2020 22:21:19

Posso confermare che viene attivato prima che il post finisca di salvarsi. Ho aggiunto una nuova risposta che penso potrebbe funzionare per attivare il codice solo dopo il completamento del salvataggio del post: https://wordpress.stackexchange.com/a/390543/171971

andergmartins andergmartins
15 giu 2021 03:34:13
0

Ho scritto un articolo sul blog riguardo questo - https://thewpvoyage.com/how-to-detect-when-a-post-is-done-saving-in-wordpress-gutenberg/

Puoi utilizzare il seguente hook:

import { useBlockProps } from '@wordpress/block-editor';
import { useRef, useState, useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

/**
 * Restituisce `true` se il post è stato salvato, `false` altrimenti.
 *
 * @returns {Boolean}
 */
const useAfterSave = () => {
    const [ isPostSaved, setIsPostSaved ] = useState( false );
    const isPostSavingInProgress = useRef( false );
    const { isSavingPost, isAutosavingPost } = useSelect( ( __select ) => {
        return {
            isSavingPost: __select( 'core/editor' ).isSavingPost(),
            isAutosavingPost: __select( 'core/editor' ).isAutosavingPost(),
        }
    } );

    useEffect( () => {
        if ( ( isSavingPost || isAutosavingPost ) && ! isPostSavingInProgress.current ) {
            setIsPostSaved( false );
            isPostSavingInProgress.current = true;
        }
        if ( ! ( isSavingPost || isAutosavingPost ) && isPostSavingInProgress.current ) {
            // Codice da eseguire dopo che il post è stato salvato.
            setIsPostSaved( true );
            isPostSavingInProgress.current = false;
        }
    }, [ isSavingPost, isAutosavingPost ] );

    return isPostSaved;
};

/**
 * La funzione di modifica di un blocco di esempio.
 *
 * @return {WPElement} Elemento da renderizzare.
 */
export default function Edit() {
    const isAfterSave = useAfterSave();

    useEffect( () => {
        if ( isAfterSave ) {
            // Aggiungi qui il tuo codice che deve essere eseguito dopo il salvataggio del post.
            console.log( '...salvataggio completato...' )
        }
    }, [ isAfterSave ] );

    return (
        <p { ...useBlockProps() }>
            { __( 'Lista delle cose da fare – ciao dall\'editor!', 'todo-list' ) }
        </p>
    );
}
21 ago 2024 13:23:34