1

I'm testing the new Interactivity API and want build a block that renders the title and content of a random post.

This is the content of the render.php file:

<?php $block_attributes = get_block_wrapper_attributes() ?> <div <?php echo $block_attributes; ?> data-wp-interactive="mystore" <?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?> > <button data-wp-on--click="actions.getRandomPost">Show me a random post</button> <p data-wp-bind--hidden="!context.isOpen"> <span data-wp-text="context.randomPost.title.rendered"></span> <div data-wp-text="context.randomPost.content.rendered"></div> </p> </div> 

This is the content of the view.js file:

import { store, getContext } from '@wordpress/interactivity' store( 'mystore', { actions: { *getRandomPost() { // a generator function const context = getContext() context.isOpen = ! context.isOpen if ( context.isOpen ) { const posts = yield fetch( 'http://' + window.location.hostname + '/wp-json/wp/v2/posts' ).then( function( response ){ return response.json() } ) context.randomPost = posts[ ( Math.floor( Math.random() * posts.length ) ) ] } }, } } ) 

The issue is that the post content (context.randomPost.content.rendered) is displayed as raw HTML, without being properly interpreted as formatted HTML.

Example:

<p>Hello world! Welcome to <strong>WordPress</strong>. This is your first post. Edit or delete it, then start writing!</p> 

Is there a way to display HTML content using the wp-text directive? Is there a specific directive to render HTML content?

2 Answers 2

3

Rather than binding text with a directive, you could bind a callback with data-wp-watch that sets the inner HTML of the div when it runs:

<div data-wp-watch="callbacks.renderContent"></div> 
callbacks: { renderContent() { const context = getContext(); const element = getElement(); element.ref.innerHTML = context.randomPost.content.rendered; }, }, 

Since the callback uses context.randomPost.content.rendered, it should run any time that value changes.

3
  • I added your code and now I get an Uncaught TypeError: t.randomPost is undefined error Commented Oct 9, 2024 at 9:08
  • 1
    My code is only an example of the method. You need to make sure the variable name is correct and that it's set. Commented Oct 21, 2024 at 15:12
  • 1
    Exactly, this is the correct way to do it as of today! But just so you know, a data-wp-dangerous-html component is in the roadmap: github.com/WordPress/gutenberg/discussions/52904 Commented Nov 14, 2024 at 10:16
-1

This is the modified code that works for me based on Jacob Peattie's answer:

render.php file:

<?php $block_attributes = get_block_wrapper_attributes() ?> <div <?php echo $block_attributes; ?> data-wp-interactive="mystore" <?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false, 'randomPost' => null, ) ); ?> > <button data-wp-on--click="actions.getRandomPost">Show me a random post</button> <p data-wp-bind--hidden="!context.isOpen"> <span data-wp-text="context.randomPost.title.rendered"></span> <div data-wp-watch="callbacks.renderContent"></div> </p> </div> 

view.js file:

import { store, getContext, getElement } from '@wordpress/interactivity' store( 'mystore', { callbacks: { renderContent() { const context = getContext(); const element = getElement(); if (context.randomPost !== null) { element.ref.innerHTML = context.randomPost.content.rendered; } }, }, actions: { *getRandomPost() { // a generator function const context = getContext() context.isOpen = ! context.isOpen if ( context.isOpen ) { const posts = yield fetch( 'http://' + window.location.hostname + '/wp-json/wp/v2/posts' ).then( function( response ){ return response.json() } ) context.randomPost = posts[ ( Math.floor( Math.random() * posts.length ) ) ] } }, } } ) 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.