Content templates, part 2: Using the templates for rendering

Created on 8 April 2025, 13 days ago

Overview

This is the second part of 📌 [PoC] Introduce a `ContentTypeTemplate` config entity Active . Once you have a content template, how can you make sure that entities of that type, bundle, and view mode are rendered using XB?

Proposed resolution

As discussed with @lauriii and summarized in https://git.drupalcode.org/project/experience_builder/-/merge_requests/8...

  • Individual bundles (node types, for example) can explicitly opt into being rendered using XB. This will probably be
    stored as a third-party setting on the node type, with a checkbox on the node type edit form.
  • The "default template" for a node type is a hard-coded, immutable component tree that displays an error-like message, saying something like "No template exists for this" or similar. Lauri has a design for this, but I'm not sure if it's been fully greenlit yet.
  • At render time, XB will try to find a content template for the entity being rendered, in the view mode that was asked for. If it finds such a template, its component tree will be rendered. (If the view mode is canonical for the entity -- think full for nodes -- then exposed slots will be populated with entity-specific subtrees. But that can happen in ✨ Content templates, part 2: store a component tree in the template, and allow individual entities to fill in specific slots in that tree Active , not this issue.)
  • If XB fails to find a matching template, it'll show the "default template" which, you'll recall, is an error-like page that prompts you to create an actual template.

XB will never fall back to core's rendering mechanisms. When you opt a bundle into XB, XB will fully take responsibility for rendering the relevant entities.

User interface changes

Probably.

✨ Feature request
Status

Active

Version

0.0

Component

Theme builder

Created by

🇺🇸United States phenaproxima Massachusetts

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @phenaproxima
  • 🇺🇸United States phenaproxima Massachusetts
  • 🇺🇸United States phenaproxima Massachusetts
  • 🇺🇸United States phenaproxima Massachusetts

    I'm glad I split this into a separate issue, because after some discussion with @mglaman, this definitely opens up a (hopefully relatively small) can of worms.

    Core doesn't really have the formal concept of a canonical view mode. It has hard-coding that treats the full view mode -- supplied with all core content entity types -- as "canonical" in the sense that it's the view mode you see if you look at the entity on its own page. It is possible for that view mode to be something other than full, though.

    Complicating this is the fact that, due to the way the Field UI works, people probably configure the fields and whatnot in the default view display, and core falls back to that in most cases because the full view display probably doesn't exist...until you explicitly enable it.

    And, to pile on even further, when you opt a bundle (I'm just gonna say node type from here on out, for expediency) into XB, what happens to existing view displays? Does a template get created for the full view mode only? Or do templates get created for all view modes? If it's the former case, then what happens when you view an entity in teaser but no XB template exists for it? If it's the latter case, how do you set up the teaser template initially? We almost have to fall back to core rendering, so as not to break sites that enable XB with content and view displays already set up.

    We need to think through these things a bit more before implementation can begin in this issue. But none of this need block ✨ Content type templates, part 1: introduce a ContentTemplate config entity which always renders an empty component tree for a particular entity display Active .

  • 🇫🇮Finland lauriii Finland

    And, to pile on even further, when you opt a bundle (I'm just gonna say node type from here on out, for expediency) into XB, what happens to existing view displays? Does a template get created for the full view mode only? Or do templates get created for all view modes? If it's the former case, then what happens when you view an entity in teaser but no XB template exists for it? If it's the latter case, how do you set up the teaser template initially? We almost have to fall back to core rendering, so as not to break sites that enable XB with content and view displays already set up.

    If you are enabling XB for a content type, the expectation is that you would rebuild those view modes in XB... Because why would you be enabling XB otherwise in the first place? Thinking about this more, whether XB should overtake all of the view modes or not is a fair question. I believe I have said that it should. Thinking about this more deeply now, I'm realizing that in many cases, you would get most of the benefits of XB from using XB for the full page view mode, even if you are not migrating the rest of the view modes.

    The reason I was trying to avoid this earlier, is that if we do not move all of the view modes to XB, we will then have to allow people to also edit their old view modes which will complicate the user experience. Ideally there will be an easy way to get a view mode converted from Manage Display / Layout Builder to XB. However, even this could be tricky because there's myriad of modules extending manage display that people are using, so building a migration that works in 100% of the use cases isn't possible.

    Based on all of this, it seems that there needs to be some way for these two to co-exist to make the experience of migrating existing content types to XB reasonable. I'd like to avoid complicating the user experience for content types that do not have any non-XB view modes.

  • 🇺🇸United States mglaman WI, USA
  • 🇺🇸United States phenaproxima Massachusetts
  • 🇺🇸United States phenaproxima Massachusetts

    Looking at the designs, a thought: it seems that, with XB enabled, if you go to "Manage display" in the Field UI, you'll be kicked into XB. So what if we did the following:

    • Require a node type to opt into XB, maybe as a third-party setting on the node type form.
    • Once that's done, "Manage display" will send you to XB, and you can edit/create a template in the given view mode.
    • When rendering, XB will try to either find a template for the requested view mode, or it falls back to core so as to not break existing sites.

    This doesn't feel super elegant but maybe it's the most pragmatic solution that remains true to the designs, while not breaking existing sites.

  • 🇺🇸United States mglaman WI, USA

    I don't 100% love a 3rd party setting, but without one hijacking the "Manage Display" local task could be more difficult. My thought was "if full view mode template exists, the bundle is opted in."

  • 🇺🇸United States phenaproxima Massachusetts

    I don't mind that, but what if templates exist for every view mode except full? (An edge case, to be sure, but not an unrealistic one, especially since most people likely just configure default, not realizing that it is being used for canonical rendering.)

  • 🇺🇸United States phenaproxima Massachusetts

    Discussed this with Lauri and Callum on Zoom. Here's the plan:

    Node types are explicitly opted into XB (let's assume it's with a third-party setting). If you don't opt into XB, the node type is handled exactly the way it currently is. Nothing changes for site builders, content creators, or site visitors. You can opt a node type into XB, and later opt out; neither choice causes any data loss.

    If you do opt a node type into XB, the site builder experience and site visitor experience are both changed. Let's examine each path separately.

    For site builders:

    • Visiting the node type's "Manage display" page will always kick you into XB.
    • If there is no existing template for the canonical view mode (which we can currently assume is either full or default), you see an error-like page that prompts you create a template for that view mode. If there is an extant template for the canonical view mode, that'll be the one you're editing by default.
    • The other enabled view modes (e.g. RSS, Search index, etc.) are visible in the sidebar, under "Templates". If you click on any of those, you being creating (or editing) a content template for that view mode.

    So, to summarize: when you opt a node type into XB, you manage the displays for that node type in XB only.

    For site visitors:

    • When rendering an entity, we look for an XB template in the requested view mode. It status doesn't matter; its existence is all we care about.
    • If we find one, great! Render it.
    • If we don't, then fall back to core's rendering.

    To summarize: we render with an XB template if one exists for the specific view mode you asked for. But we fall back to core rendering at the drop of a hat, so as not to break existing sites, and to make life easier for new sites.

  • 🇺🇸United States phenaproxima Massachusetts
  • 🇺🇸United States phenaproxima Massachusetts

    Opened ✨ Content templates, the boss battle: create a UI for editing templates Active for the site builder-facing part of #12.

  • 🇺🇸United States phenaproxima Massachusetts

    Here we go.

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • Pipeline finished with Canceled
    11 days ago
    Total: 1010s
    #470502
  • Pipeline finished with Failed
    11 days ago
    Total: 2202s
    #470517
  • Pipeline finished with Failed
    11 days ago
    Total: 319s
    #470533
  • Pipeline finished with Failed
    11 days ago
    Total: 1114s
    #470534
  • Pipeline finished with Failed
    11 days ago
    Total: 1948s
    #470547
  • Pipeline finished with Failed
    11 days ago
    Total: 1528s
    #470567
  • 🇺🇸United States mglaman WI, USA

    Summarizing a call I had with @phenaproxima and @lauriii about what opting into XB rendering truly means. There was debate around a third-party setting on the bundle, a separate config object, or using the existence of a content template for the full view mode. In the end we circled back to the heuristic being: does a component tree field exist for the bundle.

    1. Checking for a field definition is reliable and is available on the entity. It does not require loading other entity types (does a template exist? load the bundle's third-party settings) or loading a different config object
    2. Templates will allow exposed props. Those exposed props have to be stored in a component tree field. That means we always need a component tree field to exist.

    When going to a bundle and opting into XB we will:

    1. Create the component tree field for the bundle (create storage if needed for the entity type)
    2. Ensure the entity type has a full view mode (core entities do, but contrib/custom may not)
    3. Copy the default view display for full (like checking display_modes_custom in EntityDisplayFormBase
    4. We will not create an empty content template for full

    This allows using XB with the bundle and allowing fallback rendering using the normal view display until the content template has been created.

  • 🇺🇸United States phenaproxima Massachusetts

    We also agreed that opting content types into XB properly (i.e., ensuring the proper view modes exist, and the XB field) is not in scope here. We'll have to open a follow-up for it. What this issue and test coverage does confirm is that the presence of a component_tree field is the indicator that a content type is opted in.

  • Pipeline finished with Failed
    11 days ago
    Total: 603s
    #470585
  • Pipeline finished with Failed
    11 days ago
    Total: 579s
    #470588
  • Pipeline finished with Running
    11 days ago
    #470600
  • Pipeline finished with Failed
    11 days ago
    Total: 925s
    #470592
  • 🇺🇸United States mglaman WI, USA

    +1, matches how we discussed – field exists, to a template check, render if template exists, otherwise fallback to normal rendering

  • 🇺🇸United States phenaproxima Massachusetts

    Updated ✨ Content templates, the boss battle: create a UI for editing templates Active with what was discussed in #20 as far as opt-in goes. So we don't need a separate follow-up here.

  • Pipeline finished with Canceled
    11 days ago
    Total: 255s
    #470668
  • Pipeline finished with Failed
    11 days ago
    Total: 1626s
    #470669
  • First commit to issue fork.
  • Pipeline finished with Canceled
    6 days ago
    Total: 376s
    #473974
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Looking great! 😄

    But not quite ready to go in yet, because of the following non-nitpicky observations:

    1. This still executes hook_entity_display_build_alter() + hook_entity_prepare_view(), which will break existing implementations/not work → , a PoC commit explains why, and @lauriii confirmed at #3511366 is not necessary
    2. The static caching this adds should AFAICT be moved into ComponentTreeLoader, which would both simplify the code here, and benefit all of XB, and avoid re-expanding XB's API surface.
    3. Docs updates are missing from docs/config-management.md#3.5
  • Pipeline finished with Failed
    6 days ago
    Total: 890s
    #473972
  • Pipeline finished with Failed
    6 days ago
    Total: 1729s
    #473978
  • Pipeline finished with Failed
    6 days ago
    Total: 1818s
    #474059
  • Pipeline finished with Failed
    6 days ago
    Total: 1800s
    #474166
  • Pipeline finished with Failed
    6 days ago
    Total: 1586s
    #474205
  • 🇺🇸United States phenaproxima Massachusetts

    Docs updated. I believe all feedback is now addressed, although there is one commented-out assertion that I think I need @larowlan's input on.

  • Pipeline finished with Failed
    6 days ago
    Total: 2162s
    #474276
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Nice work here!

    This is now on the verge of RTBC, with only one crucial comment missing — I proposed a sample comment for making this sufficiently clear for the next person/reader/contributor to understand how ContentTemplateAwareViewBuilder then actually renders those content entities that it has a ContentTemplate for! It's quite indirect, so not at all obvious, took me ~10 mins to understand 😅

  • 🇺🇸United States phenaproxima Massachusetts

    Agreed -- I have added a comment that should hopefully make clearer how the render execution flow works. Thanks for pointing that out.

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • Pipeline finished with Failed
    5 days ago
    Total: 1707s
    #475105
  • 🇺🇸United States phenaproxima Massachusetts
Production build 0.71.5 2024