Declanșare Javascript la Salvare în Gutenberg (Block Editor)

13 nov. 2018, 03:01:39
Vizualizări: 15.2K
Voturi: 16

Am un metabox pentru care doresc să declanșez niște Javascript atunci când un post este salvat (pentru a reîmprospăta pagina în acest caz de utilizare).

În editorul clasic, acest lucru poate fi realizat printr-o simplă redirecționare legată de save_post (cu o prioritate mare).

Dar deoarece Gutenberg transformă procesul de salvare pentru metabox-urile existente în apeluri AJAX individuale acum, este nevoie de Javascript, așa că cum pot să:

  • Ascult un eveniment în care toate procesele de salvare sunt finalizate și apoi să declanșez Javascript? Dacă da, cum se numește acest eveniment? Există undeva o referință pentru aceste evenimente? SAU

  • Declanșez Javascript în interiorul procesului AJAX de salvare al metabox-ului, care poate apoi să verifice starea procesului de salvare al paginii părinte înainte de a continua?

7
Comentarii

O altă soluție ar fi să faci ca Gutenberg să reîncarce doar metabox-ul tău, sau să implementezi interfața metabox-ului în JS și să te bazezi pe stocările de date wp.data

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

@TomJNowell Am găsit această referință pe care o pot folosi pentru a verifica unele stări, dar nu sunt sigur cum să le accesez: https://wordpress.org/gutenberg/handbook/data/data-core-editor/

majick majick
13 nov. 2018 04:37:45

până acum am: de ex. wp.data.select('core/editor').isSavingPost() ... acest tip de acces nu este documentat nicăieri unde am putut să văd... și se pare că este și nesigur, deoarece returnează false după ce postarea este salvată prima dată (înainte de asta este nedefinit) indiferent dacă editorul încă salvează sau nu. facepalm

majick majick
13 nov. 2018 07:50:11

Puteți raporta și o problemă pe repository-ul Gutenberg pentru suport, este pe topic aici, dar s-ar putea să găsiți persoane mai experimentate care să răspundă acolo. De asemenea, sistemul de hook-uri JS din WP ar putea fi o posibilitate, dar asta e doar o presupunere.

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

În mod surprinzător, ceva atât de simplu precum asta este deja solicitat și nu este suportat: https://github.com/WordPress/gutenberg/issues/10044 ... de aceea încerc să găsesc o modalitate de a face asta singur.

majick majick
13 nov. 2018 09:14:42

Deci, după teste suplimentare, isSavingPost pare să funcționeze în cod (vezi răspunsul), dar când este accesat din consola browser-ului pare întotdeauna să returneze false în mod eronat. Oh well.

majick majick
13 nov. 2018 10:12:27

Destul de târziu pentru asta, dar am scris un hook care poate fi folosit pentru a detecta când procesul de salvare pe partea de server este finalizat. Puteți găsi hook-ul aici - https://thewpvoyage.com/how-to-detect-when-a-post-is-done-saving-in-wordpress-gutenberg/

Siddharth Thevaril Siddharth Thevaril
21 aug. 2024 13:22:07
Arată celelalte 2 comentarii
Toate răspunsurile la întrebare 6
6
16

Nu sunt sigur dacă există o metodă mai bună, dar ascult evenimentul subscribe în loc să adaug un event listener la buton:

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

  if (isSavingPost && !isAutosavingPost) {
    // Aici vine codul tău AJAX ......

  }
})

Documentația oficială a datelor Editorului de Postări: https://wordpress.org/gutenberg/handbook/designers-developers/developers/data/data-core-editor/

11 mar. 2019 14:11:42
Comentarii

pare mult mai curat, sunt doar curios de unde vine metoda subscribe? face parte din funcția wp.data? Nu o văd menționată în documentație.

majick majick
12 mar. 2019 15:50:33

Da, subscribe este o metodă a modulului wp.data. Deschide consola când editezi un post cu Gutenberg și rulează wp.data. Aceasta listează toate metodele disponibile ale modulului de date.

tomyam tomyam
13 mar. 2019 10:37:07

bravo că ai găsit asta! e păcat că documentația Gutenberg este atât de obscur organizată și nu are suficiente exemple. plus așteptarea ca dezvoltatorii să cunoască și/sau să vrea să învețe metode React este cu adevărat prea mult... sunt sigur că poate fi un mare economisitor de timp dacă le cunoști deja, dar este o pierdere de timp reală dacă nu - mi-a luat ore întregi doar să înțeleg cum să accesez ceva util în modelul wp.data. pentru mine, revin la PHP (și editorul clasic).

majick majick
14 mar. 2019 11:30:55

Mulțumesc pentru share! Cum pot intercepta și opri actualizarea/publicarea postării pe baza unei condiții.

Mohammed AlBanna Mohammed AlBanna
12 dec. 2019 03:27:39

Se pare că această metodă declanșează și codul atunci când un utilizator apasă butonul "Mută în Coș" (starea postării se schimbă în "trash" și valoarea isSavingPost este "true" indiferent de acest lucru). De asemenea, un singur click pe "Actualizează" a declanșat codul de subscripție de 3 ori în cazul meu. Am ajuns să ascult pentru click pe .editor-post-publish-button, .editor-post-save-draft și .editor-post-preview.

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

Acest snippet este grozav dar va fi declanșat de mai multe ori, următorul thread explică cum să îl oprești: https://github.com/WordPress/gutenberg/issues/5975#issuecomment-483488988

csalmeida csalmeida
21 feb. 2021 19:46:06
Arată celelalte 1 comentarii
1

Bine, deci o soluție mult mai improvisată decât aș fi vrut, dar am reușit să o fac să funcționeze...

Iată o metodă ușor simplificată și abstractizată din codul meu, în caz că cineva va avea nevoie să facă același lucru (sunt sigur că mai multe plugin-uri vor avea nevoie în viitorul apropiat.)

    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('Salvare: '+postsaving+' - Autosalvare: '+autosaving+' - Succes: '+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('Este necesară reîncărcarea paginii. Reîmprospătați pagina acum?')) {
                                window.location.href = window.location.href+'&refreshed=1';
                            }
                        }
                    }, 1000);
                });
            }
        }, 500);
    });

...trebuie doar să schimbați metabox_input_id și trigger_value pentru a se potrivi cu ceea ce aveți nevoie. :-)

13 nov. 2018 10:04:12
Comentarii

Aceasta a fost utilă, singurul exemplu de referință pe care l-am găsit pentru accesarea ierarhiei modulelor JavaScript din Gutenberg: https://github.com/front/gutenberg-js

majick majick
13 nov. 2018 10:18:26
0

Dacă cineva este încă interesat, am găsit o metodă simplă pentru a executa ceva imediat DUPA ce editorul de blocuri (Gutenberg) finalizează publicarea/actualizarea unui articol:

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

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

    return savePost(options)
        .then(() => {
            // Faceți ceva după ce articolul a fost salvat efectiv în mod asincron.
            console.log('Articolul a fost salvat.')

            if (!options.isAutosave) {
               // Acesta nu este un salvare automată.
            }
        })
}

Practic, fragmentul de cod de mai suprascrie funcția nativă savePost().
Deci o suprascrieți cu propria funcție, apelați din nou savePost() în interiorul ei și profitați de promisiunea returnată folosind then.

27 ian. 2023 22:48:36
1

Pentru a declanșa acțiunea (în acest caz o cerere Ajax) DUPA ce salvarea postării este COMPLETĂ, poți folosi un interval pentru a aștepta până când isSavingPost returnează false din nou.

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 iun. 2021 03:32:52
Comentarii

Cu siguranță calea de urmat - funcționează excelent. Treabă grozavă!

Spencer Bigum Spencer Bigum
6 dec. 2021 19:27:29
2

Trebuie să colectezi funcția unsubscribe din abonare și să o apelezi pentru a evita apeluri 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();


                // AJAX-ul tău AICI();

            }
        });
13 apr. 2020 14:14:19
Comentarii

Acest lucru pare să funcționeze bine, cu excepția faptului că se declanșează ÎNAINTE de salvarea completă a articolului. Codul meu plasat sub "unsubscribe() se declanșează înainte ca WP să lanseze salvarea articolului prin AJAX. Există o soluție pentru a rula codul după ce WP a terminat 100% cu salvarea/actualizarea articolului?

Neoweiter Neoweiter
1 iun. 2020 22:21:19

Pot confirma că se declanșează înainte ca articolul să fie salvat complet. Am adăugat un răspuns nou care cred că ar putea funcționa pentru a se declanșa doar după ce salvarea articolului s-a finalizat: https://wordpress.stackexchange.com/a/390543/171971

andergmartins andergmartins
15 iun. 2021 03:34:13
0

Am scris un articol pe blog despre acest subiect - https://thewpvoyage.com/how-to-detect-when-a-post-is-done-saving-in-wordpress-gutenberg/

Poți folosi următorul hook:

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

/**
 * Returnează `true` dacă postarea a fost salvată, `false` în caz contrar.
 *
 * @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 ) {
            // Codul care rulează după ce postarea a fost salvată.
            setIsPostSaved( true );
            isPostSavingInProgress.current = false;
        }
    }, [ isSavingPost, isAutosavingPost ] );

    return isPostSaved;
};

/**
 * Funcția de editare a unui bloc exemplu.
 *
 * @return {WPElement} Elementul de randat.
 */
export default function Edit() {
    const isAfterSave = useAfterSave();

    useEffect( () => {
        if ( isAfterSave ) {
            // Adaugă aici codul care trebuie să ruleze după salvarea postării.
            console.log( '...salvare finalizată...' )
        }
    }, [ isAfterSave ] );

    return (
        <p { ...useBlockProps() }>
            { __( 'Listă de Sarcini – salut de la editor!', 'todo-list' ) }
        </p>
    );
}
21 aug. 2024 13:23:34