How to listen to editor events and validate content (JS) in WordPress

Contents

Overview

This article shows in exhaustive detail how to listen to editor events and validate content in WordPress using JavaScript. It covers the modern Block Editor (Gutenberg) and the Classic Editor (TinyMCE), explains the relevant APIs, demonstrates practical examples (including blocking post saves and adding user notices), and gives best practices and troubleshooting tips. All examples are ready to paste into a plugin or theme with minimal adaptation.

Which editors and APIs this covers

  • Gutenberg / Block Editor — Uses the @wordpress packages exposed on the global wp object in the editor: wp.data, wp.blocks, wp.blockEditor, wp.plugins, wp.notices, etc.
  • Classic Editor (TinyMCE) — Uses TinyMCE and the post form (post ID post) submit flow.
  • Server-side validation — Always recommended in addition to client-side checks. Examples below show how to combine both.

Core concepts you should know

  • wp.data.subscribe() — Subscribe to store changes used for change detection in Gutenberg.
  • wp.data.select() and wp.data.dispatch() — Read and modify editor state (get content, block list, lock saving, create notices).
  • wp.blocks.parse() and select(core/block-editor).getBlocks() — Parse/inspect block content and attributes.
  • Plugin UI hooks — registerPlugin and PluginPrePublishPanel let you integrate validation UI into the editor.
  • Lock/Unlock saving — dispatch(core/editor).lockPostSaving( key, message ) and unlockPostSaving to prevent publish/save while invalid state persists.
  • TinyMCE events — editor.on(changekeyupNodeChange) and intercepting post form submit (to prevent saving invalid content).

Enqueueing your JavaScript into the Gutenberg editor

Before your JS runs in the block editor, enqueue it properly from PHP and declare the necessary WordPress editor script dependencies so global packages like wp.data are available.

 Introduction,
        disallowedTags => array( script, iframe ),
    ) )
}
add_action( enqueue_block_editor_assets, myplugin_enqueue_block_editor_assets )
?>

Minimal Gutenberg change listener (with debounce)

Use wp.data.subscribe to watch the editor store for changes. Always debounce heavy validation so the editor UI doesnt stutter when typing.

/
  Example: watch the post content and run a debounced validation.
 /
( function( wp ) {
    const { subscribe, select } = wp.data
    const debounce = ( fn, wait = 300 ) => {
        let t
        return ( ...args ) => {
            clearTimeout( t )
            t = setTimeout( () => fn( ...args ), wait )
        }
    }

    let lastContent = 

    const validateContent = () => {
        const content = select( core/editor ).getEditedPostContent()
        if ( content === lastContent ) return
        lastContent = content

        // Run validation logic here.
        // For example, fail if content contains