Helper function for adding data-wp-context in PHP #53102
Replies: 14 comments 3 replies
-
I'm not familiar with there being any WordPress "template tag" that outputs the quoted value of an HTML attribute. Rather, they output either the value of the attribute ( <?php
$context = array(
'videoId' => $trailer_id
);
?>
<div
<?php echo get_block_wrapper_attributes(); ?>
<?php echo wp_context( $context ); ?>
>
...
</div> Seeing this, another possibility is the context could be passed to As for naming, maybe |
Beta Was this translation helpful? Give feedback.
-
I kind of like the explicitness of leaving
Whatever we choose, it'd also be great to think of a possible JavaScript counterpart that uses the same name, so people don't need to remember both. import { getContextAttribute } from "@wordpress/interactivity";
const Save = ({ attributes }) => {
const context = {
videoId: attributes.trailerId,
};
return (
<div data-wp-context={getContextAttribute(context)}>
...
</div>
);
}; Or this if it includes the attribute name: <div {...getContextAttribute(context)}> |
Beta Was this translation helpful? Give feedback.
-
Could there be an even more generic helper function, sort of a echo wp_element( 'div',
[
// Attributes & directives
'context' => [ 'videoId' => $trailer_id ],
'on.click' => 'play',
'style' => [ '--img-url' => $img_url ],
],
[
// Children
__('Play')
] ); I know it's not exactly the main scope, but it can introduce the feature with a nicer DX, and reduce the need to switch between HTML/PHP/JS contexts and syntax that much. (At the cost of being less explicit and HTML-like.) Maybe this makes more sense as a part of the HTML tag processor? Either way, the current way of building HTML with string concatenation or PHP tags thrown in is not exactly a comfortable experience, not to mention error-prone. With the Interactivity API it would be an even more frequent thing developers do, so it could be worth pushing for an improved solution now. |
Beta Was this translation helpful? Give feedback.
-
Along with the Interactivity API, we are promoting the adoption of the Example of the render.php file
For reference, @dmsnell started exploring something similar to what you propose here: WordPress/wordpress-develop#4065 |
Beta Was this translation helpful? Give feedback.
-
I noted in WordPress/wordpress-develop#4065 that I no longer like that solution and have proposed an alternative, something that would look more like this and in a sense feels a bit magical in how it is able to perform validation and attribute-level semantics on the data, avoiding the need for all escaping and sanitization I believe (from the calling code) echo WP_HTML::template(
'<div data-wp-context.videoId="</%id>" data-wp-on.click="play" style="--img-url: </%url>"></%label></div>',
array(
'id' => $trailer_id,
'url' => $img_url,
'label' => __( 'Play' )
)
); |
Beta Was this translation helpful? Give feedback.
-
A related issue was opened by @ryanwelcher, discussing helper functions that could write the syntax for actions and selectors. Regarding the context, what is currently supported? Is it possible to write: <div data-wp-context.videoId="123">
...
<div>
I wanted to emphasize that We could also try to handle everything behind the scenes in the following way: <?php
wp_context( array(
'videoId' => $trailer_id
) );
?>
<div data-wp-block-wrapper data-wp-context>
...
</div If we need more than one place to use the context: <?php
wp_context( array(
'videoId' => $trailer_id
) ); // The context name as 2nd param could default to 'default'
wp_context( array(
'videoId' => $trailer_id
), 'another-context' ); // The custom name for the context.
?>
<div data-wp-block-wrapper data-wp-context>
...
<div data-wp-context="another-context">
...
</div>
</div Behind the scenes, we could generate unique ids for every block instance that uses the context: global $block_directives_context;
$block_directives_context = array(
'block-abcd-default' => array(
'videoId' => 123,
),
'block-efgh-default' => array(
'videoId' => 456,
),
'block-efgh-another-context' => array(
'videoId' => 789
),
); We would have to expose that also to Javascript and rewrite the HTML to connect it on the client, example for both snippets: <div data-wp-block-wrapper data-wp-context="block-abcd-default">
...
</div <div data-wp-block-wrapper data-wp-context="block-efgh-default">
...
<div data-wp-context="block-efgh-another-context">
...
</div>
</div |
Beta Was this translation helpful? Give feedback.
-
No, but it won't be hard to implement, even with namespaces:
Also possible and not difficult to implement. We only need to serialize them: <script type="application/json" id="wp-interactivity-contexts">
{
"block-abcd-default": { ... },
"block-efgh-default": { ... }
}
</script> I like both ideas 🙂 |
Beta Was this translation helpful? Give feedback.
-
Alternative to something like Regardless of which option we choose, it would be great to align the approaches between JSX and PHP to be of similar nature. |
Beta Was this translation helpful? Give feedback.
-
Ohhh, I just realized that there's a problem with this syntax because uppercase is sadly not preserved by the DOM parser 🙁 |
Beta Was this translation helpful? Give feedback.
-
@luisherranz attribute and tag names are case-insensitive. CSS class names are maybe the only thing with case sensitivity. |
Beta Was this translation helpful? Give feedback.
-
There's always the possibility of writing each part in kebab-case.
Then, inside the context directive, just do |
Beta Was this translation helpful? Give feedback.
-
If we finally go with
I guess it's fine 🤷♂️😄 |
Beta Was this translation helpful? Give feedback.
-
It turns out it's not that easy to escape a JSON and place it in an attibute, so we should keep looking into this. A new idea could be to use a It would be something like this for render callbacks: function render() {
$context = array(
'someValue' => 'some value',
);
return sprintf('
<div
%1$s
%2$s
>
...
</div>
',
get_block_wrapper_attributes(),
wp_directive( 'context', $context ),
);
} Something like this for <?php
$context = array(
'someValue' => 'some value',
);
?>
<div
<?php echo get_block_wrapper_attributes(); ?>
<?php echo wp_directive( 'context', $context ); ?>
>
...
</div> And something like this for the HTML Tag Processor: function( $block_content ) {
$p = new WP_HTML_Tag_Processor( $block_content );
$p->next_tag( 'DIV' );
$p->set_directive( 'context', $context );
return $p->get_updated_html();
} Namespaces are now optional, so they could be included as an option: wp_directive( 'context', $context, array(
'namespace' => 'another-namespace',
) ); |
Beta Was this translation helpful? Give feedback.
-
This was finally added in WP 6.5: https://developer.wordpress.org/reference/functions/wp_interactivity_data_wp_context/ Closing this as completed 🙂 |
Beta Was this translation helpful? Give feedback.
-
We were thinking about adding a function helper for
data-wp-context
in PHP.Something like this:
Internally, it should process the array with things like
esc_attr
orwp_json_encode
. It could potentially take care of security.Let's discuss:
Related PR: WordPress/wp-movies-demo#41
Beta Was this translation helpful? Give feedback.
All reactions