πŸ’₯ TRENDING: Block editor/reference guides/interactivity api/api reference - High Quality

API Reference

Interactivity API is only available for WordPress 6.5 and above.

To add interactions to blocks using the Interactivity API, developers can use:

  • Directives: Added to the markup to add specific behavior to the DOM elements of the block
  • Store: Contains the logic and data (state, actions, side effects, etc.) needed for the behavior

DOM elements are connected to data stored in the state and context through directives. If data in the state or context change directives will react to those changes, updating the DOM accordingly (see diagram).

State & Directives

What are directives?

Directives are custom attributes that are added to the markup of your block to add behavior to its DOM elements. This can be done in the render.php file (for dynamic blocks) or the save.js file (for static blocks).

Interactivity API directives use the data- prefix. Here’s an example of directives used in HTML markup.

<div
    data-wp-interactive="myPlugin"
    data-wp-context='{ "isOpen": false }'
    data-wp-watch="callbacks.logIsOpen"
>
    <button
        data-wp-on--click="actions.toggle"
        data-wp-bind--aria-expanded="context.isOpen"
        aria-controls="p-1"
    >
        Toggle
    </button>

    <p id="p-1" data-wp-bind--hidden="!context.isOpen">
        This element is now visible!
    </p>
</div>

Directives can also be injected dynamically using the HTML Tag Processor.

With directives, you can directly manage interactions such as side effects, state, event handlers, attributes, or content.

List of Directives

wp-interactive

The wp-interactive directive “activates” the interactivity for the DOM element and its children through the Interactivity API (directives and store). The directive includes a namespace to reference a specific store, that can be set as a string or an object.

<!-- Let's make this element and its children interactive and set the namespace -->
<div
    data-wp-interactive="myPlugin"
    data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }'
>
    <p>
        I'm interactive now,
        <span data-wp-style--background-color="context.myBgColor"
            >and I can use directives!</span
        >
    </p>
    <div>
        <p>
            I'm also interactive,
            <span data-wp-style--color="context.myColor"
                >and I can also use directives!</span
            >
        </p>
    </div>
</div>

<!-- This is also valid -->
<div
    data-wp-interactive='{ "namespace": "myPlugin" }'
    data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }'
>
    <p>
        I'm interactive now,
        <span data-wp-style--background-color="context.myBgColor"
            >and I can use directives!</span
        >
    </p>
    <div>
        <p>
            I'm also interactive,
            <span data-wp-style--color="context.myColor"
                >and I can also use directives!</span
            >
        </p>
    </div>
</div>
The use of data-wp-interactive is a requirement for the Interactivity API “engine” to work. In the following examples the data-wp-interactive has not been added for the sake of simplicity. Also, the data-wp-interactive directive will be injected automatically in the future.

wp-context

It provides a local state available to a specific HTML node and its children.

The wp-context directive accepts a stringified JSON as a value.

// render.php
<div data-wp-context='{ "post": { "id": <?php echo $post->ID; ?> } }' >
  <button data-wp-on--click="actions.logId" >
    Click Me!
  </button>
</div>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        logId: () => {
            const { post } = getContext();
            console.log( post.id );
        },
    },
} );

Different contexts can be defined at different levels, and deeper levels will merge their own context with any parent one:

<div data-wp-context='{ "foo": "bar" }'>
    <span data-wp-text="context.foo"><!-- Will output: "bar" --></span>

    <div data-wp-context='{ "bar": "baz" }'>
        <span data-wp-text="context.foo"><!-- Will output: "bar" --></span>

        <div data-wp-context='{ "foo": "bob" }'>
            <span data-wp-text="context.foo"><!-- Will output: "bob" --></span>
        </div>
    </div>
</div>

wp-bind

This directive allows setting HTML attributes on elements based on a boolean or string value. It follows the syntax data-wp-bind--attribute.

<li data-wp-context='{ "isMenuOpen": false }'>
    <button
        data-wp-on--click="actions.toggleMenu"
        data-wp-bind--aria-expanded="context.isMenuOpen"
    >
        Toggle
    </button>
    <div data-wp-bind--hidden="!context.isMenuOpen">
        <span>Title</span>
        <ul>
            SUBMENU ITEMS
        </ul>
    </div>
</li>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        toggleMenu: () => {
            const context = getContext();
            context.isMenuOpen = ! context.isMenuOpen;
        },
    },
} );

The wp-bind directive is executed:

  • When the element is created
  • Each time there’s a change on any of the properties of the state or context involved in getting the final value of the directive (inside the callback or the expression passed as reference)

When wp-bind directive references a callback to get its final value:

  • The wp-bind directive will be executed each time there’s a change on any of the properties of the state or context used inside this callback.
  • The returned value in the callback function is used to change the value of the associated attribute.

The wp-bind will do different things when the DOM element is applied, depending on its value:

  • If the value is true, the attribute is added: <div attribute>
  • If the value is false, the attribute is removed: <div>
  • If the value is a string, the attribute is added with its value assigned: <div attribute="value"
  • If the attribute name starts with aria- or data- and the value is boolean (either true or false), the attribute is added to the DOM with the boolean value assigned as a string: <div aria-attribute="true">

wp-class

This directive adds or removes a class to an HTML element, depending on a boolean value. It follows the syntax data-wp-class--classname.

<div>
    <li
        data-wp-context='{ "isSelected": false }'
        data-wp-on--click="actions.toggleSelection"
        data-wp-class--selected="context.isSelected"
    >
        Option 1
    </li>
    <li
        data-wp-context='{ "isSelected": false }'
        data-wp-on--click="actions.toggleSelection"
        data-wp-class--selected="context.isSelected"
    >
        Option 2
    </li>
</div>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        toggleSelection: () => {
            const context = getContext();
            context.isSelected = ! context.isSelected;
        },
    },
} );

The wp-class directive is executed:

  • When the element is created
  • Each time there’s a change on any of the properties of the state or context involved in getting the final value of the directive (inside the callback or the expression passed as reference)

The boolean value received by the directive is used to toggle (add when true or remove when false) the associated class name from the class attribute.

It’s important to note that when using the wp-class directive, it’s recommended to use kebab-case for class names instead of camelCase. This is because HTML attributes are not case-sensitive, and HTML will treat data-wp-class--isDark the same as data-wp-class--isdark or DATA-WP-CLASS--ISDARK.

So, for example, use the class name is-dark instead of isDark and data-wp-class--is-dark instead of data-wp-class--isDark:

<!-- Recommended -->
<div data-wp-class--is-dark="context.isDarkMode">
    <!-- ... -->
</div>

<!-- Not recommended -->
<div data-wp-class--isDark="context.isDarkMode">
    <!-- ... -->
</div>
/* Recommended */
.is-dark {
    /* ... */
}

/* Not recommended */
.isDark {
    /* ... */
}

wp-style

This directive adds or removes inline style to an HTML element, depending on its value. It follows the syntax data-wp-style--css-property.

<div data-wp-context='{ "color": "red" }'>
    <button data-wp-on--click="actions.toggleContextColor">
        Toggle Color Text
    </button>
    <p data-wp-style--color="context.color">Hello World!</p>
</div>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        toggleContextColor: () => {
            const context = getContext();
            context.color = context.color === 'red' ? 'blue' : 'red';
        },
    },
} );

The wp-style directive is executed:

  • When the element is created
  • Each time there’s a change on any of the properties of the state or context involved in getting the final value of the directive (inside the callback or the expression passed as reference)

The value received by the directive is used to add or remove the style attribute with the associated CSS property:

  • If the value is false, the style attribute is removed: <div>
  • If the value is a string, the attribute is added with its value assigned: <div style="css-property: value;">

wp-text

It sets the inner text of an HTML element.

<div data-wp-context='{ "text": "Text 1" }'>
    <span data-wp-text="context.text"></span>
    <button data-wp-on--click="actions.toggleContextText">
        Toggle Context Text
    </button>
</div>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        toggleContextText: () => {
            const context = getContext();
            context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1';
        },
    },
} );

The wp-text directive is executed:

  • When the element is created
  • Each time there’s a change on any of the properties of the state or context involved in getting the final value of the directive (inside the callback or the expression passed as reference)

The returned value is used to change the inner content of the element: <div>value</div>.

wp-on

Consider using the more performant wp-on-async instead if your directive code does not need synchronous access to the event object. If synchronous access is required, consider implementing an async action which yields to the main thread after calling the synchronous API.

This directive runs code on dispatched DOM events like click or keyup. The syntax is data-wp-on--[event] (like data-wp-on--click or data-wp-on--keyup).

<button data-wp-on--click="actions.logTime" >
  Click Me!
</button>
See store used with the directive above
store( 'myPlugin', {
    actions: {
        logTime: ( event ) => {
            console.log( new Date() );
        },
    },
} );

The wp-on directive is executed each time the associated event is triggered.

The callback passed as the reference receives the event (event), and the returned value by this callback is ignored.

wp-on-async

This directive is a more performant approach for wp-on. It immediately yields to main to avoid contributing to a long task, allowing other interactions that otherwise would be waiting on the main thread to run sooner. Use this async version whenever there is no need for synchronous access to the event object, in particular the methods event.preventDefault(), event.stopPropagation(), and event.stopImmediatePropagation().

wp-on-window

Consider using the more performant wp-on-async-window instead if your directive code does not need synchronous access to the event object. If synchronous access is required, consider implementing an async action which yields to the main thread after calling the synchronous API.

This directive allows you to attach global window events like resize, copy, and focus and then execute a defined callback when those happen.

List of supported window events.

The syntax of this directive is data-wp-on-window--[window-event] (like data-wp-on-window--resize