It seems that now it's not allowed on purpose according to #2149 but it really limits use and re-use of templates.
Current workaround is to instantiate and attach the nested template with code by replacing <child-template> tag with <slot></slot> and appending the child-template to parent-template in Java.
In the general case, this is really an "impossible" feature to support since the element defined might be instantiated any number of times. One could in theory allow @Id Collection<ComponentType> instead of just @Id ComponentType for anything inside a sub template, but this would most likely not be very useful in practice.
The special case of <dom-if> is somewhat easer to deal with since the number of instances is always either 0 or 1, but the case when there are 0 instances would still be quite weird. Consider a template with <template is="dom-if" if="_condition(prop)"><input id="phantom"></template> and a corresponding @Id Input phantom field on the server. What should happen if doing phantom.getElement().callFunction("focus") while the condition is false?
phantom is currently null.Another similar question is what phantom.getElement().getParent() should return and whether the component's onAttach handler would be run.
Polymer also takes a similar stance by not making elements inside subtemplates available as this.$.<elementId>.
It is still a very relevant use case to conditionally leave out some parts of the element hierarchy defined by the template. I'm wondering if it would be more straightforward and logical if the way you do that with instances managed from the server would be through that instance instead of doing it through the template, i.e. phantom.setVisible(false) as suggested in https://github.com/vaadin/flow/issues/2187.
There was a confusion about template in template and nested template, this issue remains open as a feature request for nested template support, and #2245 was created as a bug for @Id support in template in template.
The lack of this feature does affect the developer experience. And鈥攆rom my perspective鈥攊n case of conditional templates it makes the DX _a lot_ worse.
For example:
@Id("storefront-item")
private StorefrontItem storefrontItem;
@Id("order-detail")
private OrderDetail orderDetail;
has to be turned into
private StorefrontItem storefrontItem;
private OrderDetail orderDetail;
public StorefrontItemDetailWrapper() {
storefrontItem = new StorefrontItem();
storefrontItem.getElement().setAttribute("slot", "storefront-item");
getElement().appendChild(storefrontItem.getElement());
orderDetail = new OrderDetail();
orderDetail.getElement().setAttribute("slot", "order-detail");
getElement().appendChild(orderDetail.getElement());
}
Suggestion: make the elements inside the conditional templates Optional.
For example:
@Id("storefront-item")
private Optional<StorefrontItem> storefrontItem;
@Id("order-detail")
private Optional<OrderDetail> orderDetail;
The problem is that we'd have to build custom support for each potential use of templates.
Some examples:
<template is="dom-if" condition="[[model.value]]">
<vaadin-button id="button1">Button 1</vaadin-button>
</template>
<template is="dom-if" condition="[[model.value]]" restamp>
<vaadin-button id="button2>Button 2</vaadin-button>
</template>
<template is="dom-if" condition="_computedCondition([[model.value]])">
<vaadin-button id="button3">Button 3</vaadin-button>
</template>
<template is="dom-repeat" items="[[model.items]]">
<vaadin-button id="button4">Button [[item.value]]</vaadin-button>
</template>
In each case, there's a different logic for what value the @Id Java field should have.
In addition to these, there are also known templates for at least <vaadin-grid>, <vaadin-combo-box>, <vaadin-dialog> and <vaadin-context-menu>, not to mention all the third party components that might also support templates in different ways. Each of them have different logic for when the template is stamped and how many copies there are.
As long as dom-if is mainly used for presentational reasons, you can bind to the hidden attribute instead.
We _could_ start out by implementing support for only simple dom-if without restamp and no support for computed properties, but I fear it would open up an endless can of worms.
This should be fixed by #3057.
Closing as a duplicate of #3057.
I don't understand how this would be fixed by #3057. Is it now possible to use @Id for an element inside <template is="dom-repeat">?
Closed by mistake.
Most helpful comment
The lack of this feature does affect the developer experience. And鈥攆rom my perspective鈥攊n case of conditional templates it makes the DX _a lot_ worse.
For example:
has to be turned into
Suggestion: make the elements inside the conditional templates
Optional.For example: