admin管理员组文章数量:1122846
So I have a metabox which I want to trigger some Javascript when a post is saved (to refresh the page in this use case.)
In Classic Editor, this can be done via a simple redirect hooked to save_post
(with a high priority)
But since Gutenberg converts the saving process for existing metaboxes into individual AJAX calls now, it needs to be javascript, so how do I either:
Listen for an event where all the saving processes are complete and then trigger the javascript? If so what is this event called? Is there a reference to these events anywhere yet? OR
Trigger javascript inside the metabox saving AJAX process, which can then check the state of the parent page saving process before continuing?
So I have a metabox which I want to trigger some Javascript when a post is saved (to refresh the page in this use case.)
In Classic Editor, this can be done via a simple redirect hooked to save_post
(with a high priority)
But since Gutenberg converts the saving process for existing metaboxes into individual AJAX calls now, it needs to be javascript, so how do I either:
Listen for an event where all the saving processes are complete and then trigger the javascript? If so what is this event called? Is there a reference to these events anywhere yet? OR
Trigger javascript inside the metabox saving AJAX process, which can then check the state of the parent page saving process before continuing?
6 Answers
Reset to default 16Not sure if there is a better way, but I am listening to subscribe
rather than adding an event listener to the button:
wp.data.subscribe(function () {
var isSavingPost = wp.data.select('core/editor').isSavingPost();
var isAutosavingPost = wp.data.select('core/editor').isAutosavingPost();
if (isSavingPost && !isAutosavingPost) {
// Here goes your AJAX code ......
}
})
Official docs of the Post Editor data: https://wordpress.org/gutenberg/handbook/designers-developers/developers/data/data-core-editor/
Okay, so way way more hacky solution than I wanted, but got it working...
Here is a slightly simplified and abstracted way of doing it from my code, in case anyone ever needs to do the same (as I'm sure more plugins will in the near future.)
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('Saving: '+postsaving+' - Autosaving: '+autosaving+' - Success: '+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('Page reload required. Refresh the page now?')) {
window.location.href = window.location.href+'&refreshed=1';
}
}
}, 1000);
});
}
}, 500);
});
...just need to change metabox_input_id
and trigger_value
to match as needed. :-)
In order to trigger the action (in this case an Ajax request) AFTER the post save is COMPLETE, you can use an interval to wait until the isSavingPost returns false again.
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);
}
}
});
If someone is still interested I came up with a simple way to actually execute something right AFTER the block editor (Gutenberg) finishes a post publish/update:
const editor = window.wp.data.dispatch('core/editor')
const savePost = editor.savePost
editor.savePost = function (options) {
options = options || {}
return savePost(options)
.then(() => {
// Do something after the post was actually asynchronous saved.
console.log('The post was saved.')
if (!options.isAutosave) {
// This is not an autosave.
}
})
}
Basically the snippet above overrides the native savePost()
function.
So you override it with your own function, call savePost()
again inside it and take advantage of the promise returned just by using then
.
You need collect unsubscribe function from subscribe and call to avoid multiples time call.
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();
// your AJAX HERE();
}
});
I wrote a blog post about this - https://thewpvoyage.com/how-to-detect-when-a-post-is-done-saving-in-wordpress-gutenberg/
You can use the following hook:
import { useBlockProps } from '@wordpress/block-editor';
import { useRef, useState, useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
/**
* Returns `true` if the post is done saving, `false` otherwise.
*
* @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 ) {
// Code to run after post is done saving.
setIsPostSaved( true );
isPostSavingInProgress.current = false;
}
}, [ isSavingPost, isAutosavingPost ] );
return isPostSaved;
};
/**
* The edit function of an example block.
*
* @return {WPElement} Element to render.
*/
export default function Edit() {
const isAfterSave = useAfterSave();
useEffect( () => {
if ( isAfterSave ) {
// Add your code here that must run after the post is saved.
console.log( '...done saving...' )
}
}, [ isAfterSave ] );
return (
<p { ...useBlockProps() }>
{ __( 'Todo List – hello from the editor!', 'todo-list' ) }
</p>
);
}
本文标签: metaboxTrigger Javascript on Gutenberg (Block Editor) Save
版权声明:本文标题:metabox - Trigger Javascript on Gutenberg (Block Editor) Save 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736297266a1929974.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
wp.data
data stores – Tom J Nowell ♦ Commented Nov 13, 2018 at 2:07wp.data.select('core/editor').isSavingPost()
... this kind of access is not documented anywhere I can see... and it seems also unreliable as it returnsfalse
after the post is first saved (before that it is undefined) whether the editor is still saving or not. facepalm – majick Commented Nov 13, 2018 at 5:50