Expand my Community achievements bar.

SOLVED

How to include a component more than once in another component using Angular?

Avatar

Level 2

We have an AEM + Angular code setup. There is a requirement to add a reusable link object/resource, that can be added to many different dialogs under different resource names "primaryCTA", "secondaryCTA", "link" nodes in Banner component, for example.

It is as easy as doing a 

<sly data-sly-resource="${'primaryCTA' @ resourceType='my-project/components/cta-link'}" />
<sly
data-sly-resource="${'secondaryCTA' @ resourceType='my-project/components/cta-link'}" />

in HTL. However, we need similar solution with Angular.

A dirty way of achieving this to have following in CTA dialog:

<primaryCTA jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<id jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Link id" name="./primaryCTA/id" />
<text jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Link text" name="./primaryCTA/text" />
<href jcr:primaryType="nt:unstructured" fieldLabel="HREF Link URL" sling:resourceType="granite/ui/components/coral/foundation/form/pathfield" rootPath="/content/" name="./primaryCTA/href" />
</items>
</primaryCTA>
<secondaryCTA jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<id jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Link id" name="./secondaryCTA/id" />
<text jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Link text" name="./secondaryCTA/text" />
<href jcr:primaryType="nt:unstructured" fieldLabel="HREF Link URL" sling:resourceType="granite/ui/components/coral/foundation/form/pathfield" rootPath="/content/" name="./secondaryCTA/href" />
</items>
</primaryCTA>

 and include it in my parent Banner component dialog:

<primaryCTA jcr:primaryType="nt:unstructured" jcr:title="Primary CTA" granite:class="field-group-border" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset">
<items jcr:primaryType="nt:unstructured">
<primaryCTA jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/include" path="my-project/components/cta-link/items/primaryCTA" />
</items>
</primaryCTA>
<secondaryCTA jcr:primaryType="nt:unstructured" jcr:title="Secondary CTA" granite:class="field-group-border" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset">
<items jcr:primaryType="nt:unstructured">
<secondaryCTA jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/include" path="my-project/components/cta-link/items/secondaryCTA" />
</items>
</secondaryCTA>

But this means duplication of code and not following DRY principles. Also we'd need a dialog for each different name.

Does anybody have a clean way of introducing a node parent on CTA so we can avoid the duplicate code within CTA dialog?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

I think you can submit an idea in here, I'm sure this scenario must be useful and required for more than 1 use-case. A JCR property which will also be the node name. I think it should be pretty easy to implement through SLING.

View solution in original post

6 Replies

Avatar

Community Advisor

Hi @snehR ,

 

Please correct me if my understanding is wrong.

 

You want to add an element/component within another component, but multiple times. And, you want the name to be different (authorable).

 

Now, if you want the names to be authorable, you would need to have a dialog for the parent component.

Why not just create the dialog as a multifield and write a :

<sly data-sly-resource="${properties.name @ resourceType='my-project/components/cta-link'}" />

 You can iterate over the multifield list and create as many components/node you want.

And, instead of nesting components under one another, it will automatically render the component.

If the same component(CTA Link) is an Angular component, you don't need to worry about that as well. As the Sightly script will take care of it as it would already have a call for that component.

Avatar

Level 2

Hi @Anmol_Bhardwaj 

Thank you for replying to my query. There is no HTL code, only Angular. So, we're restricted to implementing a solution in dialog. Something like a fieldset with a node name (primaryCTA / secondaryCTA etc) and including the link component tab there, instead of having same fields duplicated in link component under those names.

However, fieldset doesn't support a name.

If I don't find anything, we'll have to duplicate nodes inside link component or use multifield with link properties instead of a separate link component.

Both of those solutions seem like hacks, not clean approaches

Avatar

Community Advisor

We cannot change node name through Angular as far as I know.

But, for the other use case, you can always use a loop in the JSX as well, where you can render the component as many times as the multifield has elements. You can pass the ID as a prop, but for node name, I think you need to use HTL

Avatar

Level 2

@Anmol_Bhardwaj I thought as much. I'm not an Angular Developer and it just seemed so easy to do in HTL. However, I thought we can't be the only ones to include one component multiple times with different node names to store in under while using a JS framework.

I wish a node name was allowed under fieldset like we can with multifield.

Thank you for taking time out, I appreciate it

Avatar

Correct answer by
Community Advisor

I think you can submit an idea in here, I'm sure this scenario must be useful and required for more than 1 use-case. A JCR property which will also be the node name. I think it should be pretty easy to implement through SLING.

Avatar

Level 2

Hi @Anmol_Bhardwaj 

I know your last comment wasn't a correct reply but I think there isn't one that exists right now. It was, however, a good suggestion to submit an idea, which I did :). So, I marked it as the correct answer.