Skip to content
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

[CoreCmp] Modularize HTL markup #1893

Open
gabrielwalt opened this issue Nov 18, 2021 · 7 comments
Open

[CoreCmp] Modularize HTL markup #1893

gabrielwalt opened this issue Nov 18, 2021 · 7 comments
Milestone

Comments

@gabrielwalt
Copy link
Member

As a developer, I want to have the HTML markup modularized into HTL templates so that changing the markup for a group of elements (atom) applies to all components that render those elements.

We should have a set of common HTL templates (data-sly-tempate) for things like:

  • Title
  • Button
  • Image
  • Link
  • Text?

The HTL of the teaser component would then mostly just call these templates (data-sly-call).

@kwin
Copy link
Contributor

kwin commented Nov 18, 2021

Why not rather including the resource type scripts directly in the teaser (proper composition pattern)? That way also things like in-place editing should work as usual.

@gabrielwalt gabrielwalt added this to the 3.0.0 milestone Nov 18, 2021
@fraudoudou
Copy link
Contributor

Having the resource types in the teaser sounds great!
It's confusing for authors, that the title is not a title component and the button is not a button component. For example, our button has a style system to style it for primary and secondary action. It cannot be used for the teaser button atm, and that's some feature we get asked for frequently.

@fraudoudou
Copy link
Contributor

Plus for Dynamic Media integration it would be super nice as well if the teaser was using the image component.

@jkoebner
Copy link
Contributor

upvote! :) 👍

@gabrielwalt
Copy link
Member Author

gabrielwalt commented Dec 1, 2021

Hi @kwin and @jkoebner,

Generally, I agree with you and like the idea. However, including Sling sub-components for component composition comes with a level of complexity that I'm not sure we want to get into. Let's take the simple example of the teaser component, a typical compound component, which could in theory be a composition of the title, text, image and button components.

A first issue is the edit dialog: to be efficient, authors shouldn't have to open 4-5 different dialogs to create a teaser, so we need to assemble these dialogs into one. That could be solved with dialog tabs that include the individual atomic dialogs, but the next issue is then for the recurring properties, like the link to the target page, which should be asked only once, and not separately for the title and the image. That could be solved with some advanced logic in the dialog, but authors could still select the individual atomic components and open their dialogs directly. At that point it starts to become really tricky: we cannot use virtual components, because some components require an actual JCR node with their resource type to function (e.g. the image component requires it for the image servlet to work). That means that we must extend the page editor to prevent the direct editing of child components on compound components like the teaser that want to prevent that behaviour. And finally, how do authors define the policy of the atomic components for the specific scope of the molecule component? That would require some capability for the template editor to allow a compound component to edit the policy of all the child components it's made of…

At that point, it's already a big undertake with a lot of additional complexity, which will also come at a price regarding performance. And we're not even considering the challenge this'd cause for the data layer, where we'd rather have one "teaser" entry, rather than an entry for each atomic component it's made out of.

I have the choice: either we try to solve that problem and do nothing else for 2 months, or we just modularise the HTL files and the dialogs where we see repetition, and also work on a really smooth authoring dialog along with many other improvements we want to do to those components. Or do you see a better way to solve that?

That said, for bigger component assembly, like molecule and organism components, I think that Sling component assembly often is the way to go. But those often happen at project level as such higher-level components are frequently more project-specific.

@jckautzmann
Copy link
Contributor

jckautzmann commented Dec 13, 2021

Following options have been investigated as part of our innovation sprint (Garage Week) to support defining and accessing the specific policy of a sub-component (nested policies):

  1. Use the delegation pattern:
    the teaser node is wrapped into a title resource (similar to the image delegation pattern)
    GarageWeek2021 - composable components #1906

  2. Use a custom logic to access the nested policy of the sub-component:

  • each sub component (e.g. title) is stored in a dedicated node e.g. teaser/title
  • design and edit dialogs of the aggregate cmp (e.g. teaser) need to use the same prefix and same property names as for the sub component (e.g. title)
  • the sub component is identified with a cq:isSubComponent property set to true
    GarageWeek2021 - composable components #1910
  1. Make the WCM policy manager support nested policies:
    in com.day.cq.wcm.core.impl.policies.ContentPolicyUtils#buildInitialContentPolicyMappingPath we could add a special handling if the resource is a sub-component.
    E.g. it could suffix the structure path (responsive grid) with a path containing the sub-component:
    "/conf/core-components-examples/settings/wcm/templates/content-page/policies/jcr:content/root/responsivegrid" + "/" + "core-components-examples/components/teaser/title"

@gabrielwalt gabrielwalt changed the title Modularize HTL markup [CoreCmp] Modularize HTL markup Jan 19, 2022
@ky940819
Copy link
Contributor

ky940819 commented Mar 7, 2022

Personally, I have often wondered why this isn't already a feature higher up in the stack (i.e. a core part of AEM)?
There is already a system in AEM that sort of does this - editable templates.

With a bit of effort it seems like composite components could be a thing that follows a similar structure so that components could be composed simply by nodes/xml just as templates are. I would actually make it identical to templates in terms of how they are constructed such that if you know how to craft an editable template then you know how to craft a composite component.

In my vision every composite component would inherit from a common resource type (just like page components typically do), it would probably be very similar to (or extend from) the layout container component.

The top level of the structure would typically be "locked" so that components placed in side of the top layout container (e.g. image, text, title) could be edited, but not removed or added to. This pattern is also not uncommon in editable templates.

For dialogs, yes each atomic part of the composite component would have it's own dialog - this also improves the in-place editing experience. If you really want to, then the base composite component could have a special dialog that aggregates all the dialogs of it's children components.

Ideally, these composite components could be located in the /conf folder as editable components, but it might be nice to be able to add them under /apps as well (with a super resource type as the base composable component, so your implementation only needs the structure and initial nodes).

This still leaves policies as the big issue. Every atomic element should be able to have it's policy configured. For example, in a teaser I should be able to select a single CTA button and apply a "highlighted" style to it or something to emphasize that CTA button. The current policy system does not allow this because it doesn't allow nested policies.

The lack of nested policy support in AEM is already a frustration; for example, the policy for a component can not be configured inside of a container that is placed on the page by the user themselves. If a container component is allowed in the template, then you can configure the allowed components for that container - but not the policy mappings for those allowed components.

Allowing this would be a pretty major change in AEM, albeit a good one in my opinion. The way I envision this being implemented is to allow policy mappings to be children of policy definitions such that the structure of a template (or component) is mapped to a policy (which may be shared by multiple templates/components), and then inside that policy there are further mappings such that the policy resolution is to start by finding the proper policy from the template/component structure, and then follow the chain of mappings within that policy until you find the closest one.

This would also require some reworking of the template editor UI so that for layout containers the policy mappings for it's children can be configured inside the policy configuration dialog instead of (or in addition to) being presented on the page (as is currently the case and poses a UI limitation of sub-policies, even if the policy resolution system supported nested policies). This could either be an additional tab for sub-policy mappings, or an icon next to the allowed components so that the template editor can select the policy mapping to use for each allowed component.

Needless to say, this is a significant undertaking and would be well outside the scope of the Core Components. However, it would provide a solid framework for how to do any composite component, accelerating development time for many custom components (not all, because some complex custom components just can't be formed from the atomic units available), as well as facilitating configuration of some more complex/niche templates that might have multiple levels of nested containers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants