-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic Template Parts #32939
Comments
If I'm reading this right, you're not only suggesting improvements to the flexibility of template parts; that's just one example of a much bigger issue. Is that correct? I've run into that too, a simple example is putting the current year in a footer: Without the ability to execute arbitrary PHP/JS inside a template, custom blocks need to be created, even for trivial things. When building a custom theme for a single site, that doesn't feel practical to me. One workaround is to create a plugin that registers an "example.org footer" block for the entire footer, but that feels a bit hacky to me. |
@iandunn I created a simple block to put the date in the footer. https://github.com/mkaz/copyright-block or https://wordpress.org/plugins/copyright-block I think it is even installable from the block directory. So a potential solution for some of these micro dynamic pieces could additional blocks. However, the ability to do logic and other conditionals based on tags, pages, and template hierarchy is going to be a need. I tried to build a different header background color based on category and it required many templates or some custom CSS that couldn't be done using global styles. |
I agree, having such system we could do what we do now with PHP templates. |
Another random small thing would be linking to the homepage. In a classic theme I'd use ( I'm talking about a regular link that's outside a nav menu. ) Adding a separate block for every template tag seems like a lot of clutter, but maybe a single block could wrap them all? e.g., <!-- wp:template-tag {"function":"home_url"} /-->
<!-- wp:template-tag {"function":"bloginfo","arguments":["admin_email"]} /--> That would still be limited compared to PHP, though. |
The Home Link block was created for linking to the homepage, but there are numerous other PHP function/values that will be useful in templates. Here is a related issue highlighting a similar need: #31815 |
Is this the correct ticket in which to mention conditional display? For example, I need to be able to switch between a query loop and a "no posts found" message in e.g. block-templates/index.html. Is this not possible, or have I just not found the documentation yet? (See also #29076 (comment).) |
The |
Thanks for the information. But that's not sufficient for displaying a completely different combination of blocks when no posts are found. For example, adding text information, a sitemap, or a search form with more detailed instructions. |
Ah, I see. Then yeah, this seems like a good issue to me 👍🏻 |
I like this api for the problem/solution. I'm not sure on how and where this page/post/single/singular context is coming from? Is this something the rendering function must provide at a global level? One thing I like about block html is that it can be rendered anywhere and, ignoring server side rendering, you always get the same result.
I'd prefer any template hooks to be done in JS leaving the option to escape to php if one needs but doesn't require it for all template rendering. (I'm assuming there is an optimization where you can compile all the templates into a single network request or some sort of js bundle) |
I was able to hack together a filter that could be used to emulate a crude version of dynamic templates from a theme's functions.php. function conditional_template_part( $path, $file ) {
// Crudely simulate the $name parameter to get_template_part() for the wp:template-part block
// Example: <!-- wp:template-part {"slug":"foo-bar{-test}"} -->
// will attempt to use "foo-bar-test", and fall back to "foo-bar" if that template file does not exist
if ( false !== strpos( $path, '{' ) && !file_exists( $path ) ) {
if ( preg_match( '/[{]([-\w]+)[}]/', $path, $matches ) ) {
$name = $matches[1];
// Try "foo-bar-test"
$new_path = str_replace( '{' . $name . '}', $name, $path );
if ( file_exists( $new_path ) ) {
$path = $new_path;
} else {
// If that doesn't exist, try "foo-bar"
$new_path = str_replace( '{' . $name . '}', '', $path );
if ( file_exists( $new_path ) ) {
$path = $new_path;
}
}
}
}
return $path;
}
add_filter( 'theme_file_path', 'conditional_template_part', 10, 2 ); Obviously it only handles simple string values and doesn't handle any of the hierarchical or truly dynamic ideas discussed above. But it does work for simple cases equivalent to Note: this is only lightly tested, and I haven't really considered security. |
I don't know that the Maybe something like this, where the <!-- wp:template-part { "slug":"content", "part": "POST_TYPE" } /--> (naming things is hard, totally not tied to |
The I like the idea of having a set of tokens. It would be an extensive set and need to cover pretty much all the variables of global template hierarchy and object level (post, term, user, etc.). With that said, starting with a |
I am trying to make a block theme. I have a 3 column layout on the homepage (index.html) and want to add a 2 column layout as well. Its as easy as changing the columns:3 to columns:2 in the query (index.html) but I haven't found a way to do this. I want to have an option (in customizer) to set homepage columns. I do not want to use page templates (or set static front page). I have been searching for a solution but haven't found anything so far. Any suggestions are highly appreciated. A simple code idea would have been if($customizer_option_col_3) { run wp_query($query); |
Because block templates are HTML, the only truly dynamic pieces are the blocks themselves. However, there are many instances where theme authors need to change output based on some context. The easiest and one of the most-used examples of this is template parts.
Traditionally, to avoid repeating code, theme authors would use
get_template_part()
and some variable to create a bit of a hierarchical system. Despite its weakness of only allowing a string instead of array of possible parts, it was still useful to do something likeget_template_part( 'content', 'post' )
to search for acontent-post.php
with a fallback tocontent.php
.For more advanced use cases, developers had to go their own route with
locate_template()
(allows an array of template parts) or wrapper functions around it.Without the ability to contextually load template parts, it is creating a scenario where theme authors must break the DRY principle.
Let's suppose you have an
index.html
file that loads the header, content, and footer.Typically, the header and footer are not going to change often. However, if you want the "content" template to change for pages, you must create a top-level
page.html
template andcontent-page.html
template:Creating a whole new template to change one slug is not ideal.
If you want a different singular-view content template part, for example, you must then double up on those templates again with
singular.html
andcontent-singular.html
.Now, if you start breaking that down into smaller template parts, it becomes a tangle of repeated code. And, that means more and more opportunities for bugs.
Ideally, template parts would allow theme authors to inject some sort of hierarchy into them. One route is directly into the template part call:
<!-- wp:template-part { "slug":"content","hierarchy":["singular","single","post"] } /-->
That would look for
content-singular.html
,content-single.html
,content-post.html
, andcontent.html
. That limits the options though because it is not dynamic.A filter hook would be more useful for a true contextual system:
I already have around a couple dozen templates/parts that should be entirely unnecessary in my block theme. I expect that number to only grow.
The text was updated successfully, but these errors were encountered: