- Issue created by @wim leers
- Merge request !754Draft: Resolve #3511366 "Poc content type template config entity type" โ (Open) created by wim leers
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Updated issue summary with new design/product questions that I identified while building the PoC to predict future technical challenges: now there's not 2 but 9 challenges! ๐
FYI: I landed on the term for what @jessebaker alluded to in #3498819-5: [Needs design] Proposal: Adjust representation of Regions in the Layers UI โ .
Note that I built this config entity type PoC while taking into account all discussion-surfaced requirements outlined in the meta โ .
Omitted from the work I did:
- Per-component input (un)locking: this seems too overwhelming/too granular.
- Mostly omitted: view mode concerns. The config entity type supports storing it, but none of the semantical or UX consequences are addressed. For example: it the XB content type template for a "teaser" view mode exposes a different Content Type Slot than the one for the "default" view mode, how would the content author ever populate it? It'd always remain empty! An obvious solution seems: the "default" view mode defines the total set of Content Type Slots, and each view mode can choose to contain only a subset of them. But does this meet @lauriii's product vision? Impossible to tell: it's currently neither written down nor expressed in designs. He did express that anything beyond "default" view mode is a concern for later, so I didn't delve deeper.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
In not-yet-public docs, I encountered a functional requirement I had not read before, but it makes sense (it ties into XB product requirement
14. Configuration management
), it reads:I can make changes to the content type templates outside of the production site
โฆ which is the non-UI, but config-management-level-enforced equivalent of point 9 I surfaced in the issue summary above: .
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Additional notes while digging into this problem space and trying to think through everything:
- ๐ชโ๏ธTranslatability. A component tree will typically contain some static values. For example: a button that points to the current content entity's webshop URL, with that URL being mapped into it dynamically (
DynamicPropSource
), but the button label being defined statically because it makes no sense as structured data (so:StaticPropSource
).Any component input populated using a
DynamicPropSource
is automatically translatable, because it fetches the value from the host content entity.But any component input populated using a
StaticPropSource
is NOT translatable. At least not at this time. Because component trees in config are currently enormous JSON blobs. That's not compatible with Drupal's config translation functionality โ .
(More to follow.)
- ๐ชโ๏ธTranslatability. A component tree will typically contain some static values. For example: a button that points to the current content entity's webshop URL, with that URL being mapped into it dynamically (
- ๐ฌ๐งUnited Kingdom catch
So, rephrasing: assuming that we know which of the structured data are "meta" vs not, must every non-meta field be used somewhere in the component tree?
It's common to have fields that are only used on specific view modes, including ones that don't show on the default. An example would be a 'short summary' field that only shows on a card view mode and not on the main content.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Based on discussing ๐ฑ [META] 7. Content type templates โ aka "default layouts" โ clarify the tree+props data model Active with @lauriii this morning, a few things surfaced:
- Supporting multiple view modes MUST be supported from the start. But, only the
default
view mode will be customizable per entity. So, ateaser
view mode for example would look the same for all entities of that content entity type+bundle: the same exact XB component tree would be used for all (i.e. the one in the "teaser" Content Type Template config entity), while of course resolving the structured data mapped into the component tree (i.e. usingDynamicPropSource
s).This avoids the entire "keep Content Type Slots in sync across all Content Type Templates (one per view mode) for this content entity type+bundle" problem. ๐
- XB is used for either all or none of the view modes. IOW: as soon as you chose to use XB, all existing
EntityViewDisplay
s are ignored. Those that don't have an XB Content Type Template defined yet render nothing.Note: this will change in the far future per @lauriii: he intends to allow specifying an XB element (see ๐ Clarify "components" vs "elements" vs "patterns" Active ) to be associated with each field type, which essentially becomes the XB equivalent of "the default formatter".
- Last but not least: per @lauriii, there won't be a "search" or "search index" view mode for XB โ search must be configured to use the "default" view mode's representation of content entities both for 1) crafting a search index to power the search, 2) presenting search results. Related:
๐ฑ
[META] Support alternative renderings of prop data added for the 'full' view mode such as for search indexing or newsletters
Active
and
๐
Create a configurable search api processor for XB data
Active
.
It's not clear to me yet how that avoids the
but without elements that would 'pollute' the search results like field labels, related content blocks, CTAs, social widgets etc. so that if I search for "newsletter" or "Facebook" I don't get every article on the site back in the results, but only the ones with content actually mentioning newsletters or Facebook.
problem described in ๐ฑ [META] Support alternative renderings of prop data added for the 'full' view mode such as for search indexing or newsletters Active , though.
- Supporting multiple view modes MUST be supported from the start. But, only the
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Reflected #7 in the PoC MR: https://git.drupalcode.org/project/experience_builder/-/merge_requests/7....
Responses
Hey @wim-leers - the answers below is just my take on the problems listed ๐
- View modes - Not for me to answer
- Internal/exposed or Locked/unlocked aka Exposed Content Type Slots aka unlocked subtrees - Any slots that are used within the template should be able to be an exposed slot. They will not be able to be exposed if they currently contain any child items.
- What about the existing EntityViewDisplay(s)? - Unsure on this one, would be keen to discuss it further.
- Must every field for the content entity type+bundle be used somewhere in the component tree, because otherwise some data is invisible? - No, it would be up to whoever is creating their content template to decide what fields are mapped to their template. For example: If a product content type has a required field of โPriceโ it is up the person creating the template to ensure that it is tied to their template.
I think a good way to think of the creation of templates is similar to how it would be done with a headless CMS, in that the content model and content creation are separate from the templating layer. - Are we okay with either ignoring or breaking existing hook_entity_display_build_alter() implementations? - Not for me to answer
- Gotcha for Exposed Content Type Slots aka unlocked subtrees. - Correct, we should allow having no exposed slots for the content type.
If a user wanted to they could make the entire page a single slot, but they would still need to add a component and expose the slot in the exact same way as exposing any other slot.
- Gotcha for Exposed Content Type Slots aka unlocked subtrees. - I donโt believe we should be allowing exposed slots to include anything. By including items in a slot to also be exposed to a content editor, we open lots of ways to break templates that aren't necessary. By going this route I don't think we impede the template builder in any way. In the user flows this should become clearer.
- Gotcha for Exposed Content Type Slots aka unlocked subtrees. - Good point, as part of exposing a slot, we can ensure that thereโs a name and machine name here. Will need some designs and work on the front-end to cater for this.
- Gotcha for Exposed Content Type Slots aka unlocked subtrees. - Are you saying that when a component is added to a slot when editing content, it cannot be deleted? Or is it just that the data cannot be deleted?
Questions from me:
- Once you have made a slot exposed, are we able to revert this change? Can we turn off an exposed slot?
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
#10:
RE: your question: per discussion this morning with @lauriii: as the Site Builder modifying/creating an XB Content Type Template, you have complete freedom to completely change your mind about adding/removing exposed Content Type Slots. So the answer is: "yes, you can revert".- โ Sorry ๐ This has changed โ see #7.2. Issue summary updated in #11 ๐
- I suspect we are on the same page, but โฆ I disagree with your specific wording ๐ I know I'm gonna sound super nitpicky, but all of this is going to have enormous consequences for UX and data integrity, so I went to be painfully precise ๐ค ๐
- It should not be "any slot", because slots can live within other slots.
- Furthermore, I'm not convinced yet that only slots must be exposable as a Content Type Slot, but any component instance. That way:
- if it's a component instance without slots, it means you can modify this component instance's inputs โ for example: XB's
my-section
SDC would then be able to have inputs (image, text next to the image) that are defined in the Content Type Template, but if the Content Creator chooses, they could modify the inputs without the ability to add more component instances - if it's a component instance with >=1 slot(s), it means the Content Creator can modify as much as they like: remove the entire component tree in one of those slots, keep it empty, replace it with other component instances, or keep it all the same as in the Content Type Template
- if it's a component instance without slots, it means you can modify this component instance's inputs โ for example: XB's
- โ This has been answered by @lauriii. Issue summary updated in #11 ๐
- ๐ WFM! But would there then be affordances to ensure the Site Builder is explicitly aware of which fields (whose values) are not (yet) being presented?
- โ This has been answered by @lauriii. Issue summary updated in #11 ๐
- ๐ This ties well into what @lauriii has confirmed Product-wise โ see the updated information for Question 2 in the issue summary.
- ๐ค I'm not sure how to interpret this. Are you saying that a Site Builder should or should not be able to expose a Content Type Slot that contains some component instances populated with structured data?
- ๐
- โ
Sorry ๐ This has changed โ see #7.1. Issue summary updated in #11 ๐
(And no, that's not what I meant: I was referring to disallowing deleting Content Type Slots, but @lauriii has since said this is fine, and it's fine to lose Content Creator-crafted data.)
- ๐ฌ๐งUnited Kingdom catch
Last but not least: per @lauriii, there won't be a "search" or "search index" view mode for XB โ search must be configured to use the "default" view mode's representation of content entities both for 1) crafting a search index to power the search,
afaict this is incompatible with ๐ Create a configurable search api processor for XB data Active - which is suggesting not rendering XB at all when configuring search indexing, except via the special search API processor. I'm not convinced by that issue yet (and left a question on there which hasn't been answered yet) but has that been abandoned or is this a mistake? Using ๐ Create a configurable search api processor for XB data Active would mean either not using a view mode at all in search indexing, or a view mode minus XB data that only shows entity fields, with the XB data then provided by the separate processor.
If you had to use the default view mode and the processor it would mean double-rendering when search indexing.
2) presenting search results.
This seems unnecessarily restrictive and also unenforceable. e.g. you can configure search API views to return results from a search index, then use any view mode on the entity that you like right now - like displaying search results as a grid of cards or whatever.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
This blocks pretty much everything in ๐ฑ [META] 7. Content type templates โ aka "default layouts" โ clarify the tree+props data model Active .
In more concrete terms, it blocks ๐ Prevent fields from being deleted if they are used in Experience Builder field's dynamic prop values Active .
- ๐ง๐ชBelgium borisson_ Mechelen, ๐ง๐ช
Last but not least: per @lauriii, there won't be a "search" or "search index" view mode for XB โ search must be configured to use the "default" view mode's representation of content entities both for 1) crafting a search index to power the search, 2) presenting search results. Related: ๐ฑ [META] Support alternative renderings of prop data added for the 'full' view mode such as for search indexing or newsletters Active and ๐ Create a configurable search api processor for XB data Active
It's not clear to me yet how that avoids the
but without elements that would 'pollute' the search results like field labels, related content blocks, CTAs, social widgets etc. so that if I search for "newsletter" or "Facebook" I don't get every article on the site back in the results, but only the ones with content actually mentioning newsletters or Facebook.
problem described in ๐ฑ [META] Support alternative renderings of prop data added for the 'full' view mode such as for search indexing or newsletters Active though.
Rendering Search results in the same way as the content's detail page doe not seem like the most commonly chosen way of configuring it. I did a quick poll at the contribution room at Drupal Mountain Camp, and everyone who answered me always configures some kind of teaser, card or search-result view mode when rendering a search result page.
For the indexation part, I also don't see a way that would remove those pollutions without having a seperate view mode, but I personally think that's not as bad. When needing complete control over what all is indexed, it should be indexed using fields, because then it's possible to boost per-field. It gives a lot more control.
This however would mean something like https://www.drupal.org/project/layoutbuilder_search_api โ for all components/props, which is another approach that could be taken. This removes the double rendering that catch talked about in #13.
- ๐ฌ๐งUnited Kingdom catch
When needing complete control over what all is indexed, it should be indexed using fields, because then it's possible to boost per-field. It gives a lot more control.
This however would mean something like https://www.drupal.org/project/layoutbuilder_search_api โ for all components/props
I think that ๐ Refactor the XB field type to be multi-valued, to de-jsonify the tree, and to reference the field_union type of the prop values Active would also handle this - because the props would be available as field data to search API then without an additional translation layer.
- ๐ซ๐ฎFinland lauriii Finland
Rendering Search results in the same way as the content's detail page doe not seem like the most commonly chosen way of configuring it. I did a quick poll at the contribution room at Drupal Mountain Camp, and everyone who answered me always configures some kind of teaser, card or search-result view mode when rendering a search result page.
We should definitely support configuring customizing how content is displayed in the search results page. I'm not sure we need to do that in this issue though because it might make sense to design and implement solution specifically for that, because it's such a common use case.
- ๐ฌ๐งUnited Kingdom catch
@lauriii that's the opposite of what this says in #7:
Last but not least: per @lauriii, there won't be a "search" or "search index" view mode for XB โ search must be configured to use the "default" view mode's representation of content entities both for 1) crafting a search index to power the search, 2) presenting search results.
is there a miscommunication somewhere?
If search results use a view mode for rendering (which a lot of sites do), then it shouldn't require any special handling in XB, it just needs to not break using view modes for rendering.
The place where it might get tricky is 'results snippet' type situations where the search result is trying to show the searched keywords in the context of the results. I'm not sure how that's generally implemented in search API or not or whether it would need special handling. For me that's the least important aspect to worry about - it's the initial indexing that feels unresolved still.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
#17: that's not matching what you said earlier โ .
Unless you meant that that would be the initial state, and you intend to only use the default content type template for search indexing and a different content type template for presenting search results?
But if we do that, then it follows that the information that was matched is absent from the search result's presentation, meaning highlighting is impossible.
- ๐ซ๐ฎFinland lauriii Finland
I feel like we are talking past each other with different use cases and scenarios and concerns that are not being impacted by Experience Builder. My understanding is that there are two primary ways of configuring Search API: text based search and faceted search (as well as combination of the two).
When using text based search and the intent is to index the whole page, the "Rendered HTML output" with the default content type template (same as what user would see when navigating to the page) should be used. Search API would allow configuring other view modes to be used for indexing but those wouldn't include the content added to the slots, but only content that is being rendered through those view modes. So long as we keep view modes working, this should all work without specifically having to accommodate them. This is the same experience that you would get when using Layout Builder today.
When using the text based search, the results would often display an excerpt which is generated based on what is in the index. This allows highlighting the text that is being matched. This shouldn't require any special accommodations from XB so long as what is stored in the index is sensible.
When implementing a faceted search, it's common to configure the results to display to using a view mode like cards or search result. In this scenario, text is not being highlighted. Even in this scenario, the index may include the full rendered page, highlighting that the index is a separate concern from the presentation of the results.
- ๐ฆ๐บAustralia larowlan ๐ฆ๐บ๐.au GMT+10
Layout builder uses third party settings on the entity view display for this rather than a separate config entity.
I think that is a valid approach worth considering.I also think ๐ Decouple tree storage, introduce tree storage plugins Active is important here because our present code-path
\Drupal\experience_builder\InternalXbFieldNameResolver::getXbFieldName
falls over here - ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Layout builder uses third party settings on the entity view display for this rather than a separate config entity.
I considered that, but I think there are strong reasons against it:
- The consequence of that will be though that this new config entity type is not validatable, because
EntityViewDisplay
config entities are not yet fully validatable, with an unclear ETA for that in core. This would significantly weaken XB's14. Configuration management
product requirement. - LB predominantly uses field formatters to present structured content: it uses
FieldBlock
, which contains field formatter settings (which IIRC are treated as the default formatter settings when placing a field block). So, most of the information in theEntityViewDisplay
is still somewhat relevant when using LB. - @lauriii has indicated that it should be possible to try XB and be able to abort and go back to what you had before: plain core entity view displays, or Layout Builder entity view displays. Not touching them at all makes that an easy promise to keep.
- Finally, and probably the strongest argument: LB does a quite heavy-handed override at
\Drupal\layout_builder\Hook\LayoutBuilderHooks::entityTypeAlter()
that causes allEntityViewDisplay
config entities to use its ownLayoutBuilderEntityViewDisplay
class instead! XB cannot do the same, or it'd either break LB (race: who wins?) or require LB (definitely not the intent either). That's in the MR:
* This MUST be a new config entity type because doing something like Layout * Builder's `LayoutBuilderEntityViewDisplay` is impossible if XB wants to * provide a smooth upgrade path from Layout Builder, due to * \Drupal\layout_builder\Hook\LayoutBuilderHooks::entityTypeAlter() โ only one * module can do that!
I don't think ๐ Decouple tree storage, introduce tree storage plugins Active is a hard blocker for this issue, but I definitely agree it'd be nice to solve, especially in light of providing a smooth transition from Layout Builder into Experience Builder! (Note this will require either duplicating LB's
FieldBlock
in XB, or moving it to another module โ otherwise Layout Builder will be required forever even on sites that have all their data moved from LB to XB!) - The consequence of that will be though that this new config entity type is not validatable, because
- First commit to issue fork.
- ๐บ๐ธUnited States mglaman WI, USA
+1 to this approach! I had forgotten this issue and proof of concept existed when I had a chat with @phenaproxima where we chatted over this idea. The outcome happened to be nearly the same as this issue, except I didn't consider the possibility of having the config entity implement EntityViewDisplayInterface so we could swap it for the view display object.
I pushed a test and some wonky code to further explore. I like that it mimics how page regions work. If something exists we execute a new code path versus embedding into the existing code path.
- ๐บ๐ธUnited States mglaman WI, USA
๐ move static collect*() methods from display entity classes to EntityDisplayRepository Active would make this much easier. Then we could swap the display objects not and need hook_entity_prepare_view and hook_entity_view_alter
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
@callumharrod walked us (@lauriii, myself and David Bee) through the designs he crafted. All of us asked various questions. The PoC here is still aligned with the designs, with one exception: we're not going to be exposing a component instance as an exposed slot, but a slot in a component instance.
Walked @phenaproxima through that change, and captured this change with him together, as a way to hand this off to him: https://git.drupalcode.org/project/experience_builder/-/merge_requests/7... :)
(I'm still around, obviously!)
- First commit to issue fork.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
@phenaproxima has split this into multiple child issues ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Epic work on โจ Content type templates, part 1: introduce a ContentTemplate config entity which always renders an empty component tree for a particular entity display Active , @phenaproxima โ it is in! ๐ ๐
Also: detailed guidance/pointers at:
- Assigned to phenaproxima
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
FYI: ๐ Component trees with dynamic prop sources that introspect field values don't add the relevant fields to their dependencies Active has been fixed ๐ฅณ
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Update for #29:
- ๐ Component trees with dynamic prop sources that introspect field values don't add the relevant fields to their dependencies Active is fixed
- #3519352 is unblocked, and is in need of review by @phenaproxima at #3519352-55: Content templates, part 3b: store exposed slot subtrees on individual entities โ