Would it be possible to render an <amp-list> from a src whose URL has a variable substituted by an outer template? For example:
<div amp-access="access AND token">
<template amp-access-template type="amp-mustache">
List endpoint: /json/{{token}}.json:<br/>
<amp-list width=auto height=100 layout=fixed-height src="<%host%>/json/{{token}}.json">
<template type="amp-mustache" id="amp-template-id">
<div><a href={{url}}>{{title}}</a></div>
</template>
</amp-list>
You got the token {{token}}!
</template>
</div>
I've tried this with the amp-access sample by making the authorization endpoint return
{
"token": "examples",
"access": true
}
but I get the following error:
Template not found for <amp-list width=​"auto" height=​"100" layout=​"fixed-height" src=​"http:​/​/​localhost:​8080/​json/​examples.json" class=​"-amp-element -amp-layout-fixed-height -amp-layout-size-defined -amp-layout -amp-error" id=​"AMP_16" style=​"height:​ 100px;​">​…​</amp-list>​
Dd @ error.js:69
log.js:243 Uncaught Error: task failed: amp-list#16#L amp-list#16: Template not found for amp-list#AMP_16​​​ _reported_
at xa.f.assert (log.js:243)
at qf (template-impl.js:208)
at nf.findAndRenderTemplateArray (template-impl.js:189)
at amp-list.js:67

/to @dvoytenko
@dandv The reason for this is because currently AMP disallows nested <template> tags. I can look if I can change that, though it'd require an additional security review. That being said, I believe you can achieve something similar with this code:
<div amp-access="access AND token">
<amp-list width=auto height=100 layout=fixed-height
src="<%host%>/json/AUTHDATA(token).json">
<template type="amp-mustache" id="amp-template-id">
<div><a href={{url}}>{{title}}</a></div>
</template>
</amp-list>
</div>
@dandv — have you tried @dvoytenko's suggestion? Is the original request still needed?
From today's discussion:
Supporting nested templates would support a wider range of use-cases that we need to support soon anyway (other components like date-picker in amp-list. or even nested amp-list).
@aghassemi Would love to have this more fleshed out -- specifically use cases where "reference-template-by-id" is insufficient or awkward to use. /cc @ericlindley-g
@danielrozenberg also brought up the fact that we should clearly define what expected behavior is for this case.
<template>
{{a}} {{b}}
<template>
{{b}} {{c}}
</template>
</template>
We also discussed a possible infinite loop edge case of a self-rendering amp-list that should be addressed.
Regarding supporting nested templates:
This is something that is allowed in HTML and the way it works is that activating the outer template does not activate the inner ones. https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-gotcha
This behaviour seems compatible what we would want in AMP as well. When a parent template is rendered, the inner template is untouched and left to however needs to activate it later.
So in the case of
<div amp-access="access AND token">
<template amp-access-template type="amp-mustache">
List endpoint: /json/{{token}}.json:<br/>
<amp-list width=auto height=100 layout=fixed-height src="<%host%>/json/{{token}}.json">
<template type="amp-mustache" id="amp-template-id">
<div><a href={{url}}>{{title}}</a></div>
</template>
</amp-list>
You got the token {{token}}!
</template>
</div>
when amp-access renders the outer template, we end up with:
<div amp-access="access AND token">
List endpoint: /json/1234.json:<br/>
<amp-list width=auto height=100 layout=fixed-height src="<%host%>/json/1234.json">
<template type="amp-mustache" id="amp-template-id">
<div><a href={{url}}>{{title}}</a></div>
</template>
</amp-list>
You got the token 1234!
</div>
Note that {{token}} is NOT available in the inner template.
Now from the perspective of amp-list it has no idea it used to be in a template and when it looks for its template to render it will see
<template type="amp-mustache" id="amp-template-id">
<div><a href={{url}}>{{title}}</a></div>
</template>
and when it renders we end up with something like:
<div amp-access="access AND token">
List endpoint: /json/1234.json:<br/>
<amp-list width=auto height=100 layout=fixed-height src="<%host%>/json/1234.json">
<div><a href=foo1.com>foo1</a></div>
<div><a href=bar.com>bar</a></div>
</amp-list>
You got the token 1234!
</div>
@dvoytenko, do you remember what the security concerns were around supporting nested templates?
@choumx / @danielrozenberg, could you provide an example where we can end up in an infinite-loop?
Example of infinite loop:
<amp-list src="/json">
<template>{{ markup }}</template>
</amp-list>
Then if /json returns
[
{"markup": "<amp-list src='/json'><template>{{ markup }}</template></amp-list>"}
]
Then the <amp-list> will expand to print the markup, which would be parsed as an <amp-list> that would retrieve /json and render its inner template the same way as its parent, and so on and so forth. That's a very deliberate shoot-self-in-the-leg scenario tho
as @choumx also pointed out offline, there is no reason we can't do both (e.g support nested templates and "reference-template-by-id" eventually).
My opinion is that although both approaches can handle the same use-cases, the main difference is that in the "reference-template-by-id" approach, every templateable component needs to expose a way to reference a template id as part of its own format whereas nested-templates will just work and is future-proof.
For instance, only amp-list currently supports referencing another template via id (with the template attribute). amp-form doesn't and neither does amp-datepicker.
Both amp-form and amp-datepicker can have multiple templates for different states (e.g. success, failure in case of form. date picker can have unlimited number of templates for different days - such as tuesdays, Jan 5th , etc..).
To make "reference-template-by-id" work, both amp-form and amp-datepicker need to change their format:
There are various options discussed for amp-form in https://github.com/ampproject/amphtml/issues/7118 such as <form success-template=id> or <div submit-success template=id>
For date-picker, we haven't discussed a format that can support referencing templates by Id yet. One approach could be allowing every <template> to be a <div template=id> and handle the nuances (e.g. display:none the divs so they don't create a new line in the middle of the component, update validation rules, etc..)
@danielrozenberg, regarding infinite loop. I haven't tested but based on the code we only allow a very limited 'formatting' (e.g. <b>, <i> etc..) markup for unescaped values. So if a {{var}} has any markup other than simple tags, they get escaped (or maybe removed, not sure). Therefore {"markup": "<amp-list src='/json'><template>{{ markup }}</template></amp-list>"} is not supported.
@aghassemi I believe the only security concern for nesting templates was avoidance of recursion. Probably easy enough to control for, but must be thoroughly unit-tested.
I got this error in amp version: 1903141753530
The tag 'template' may not appear as a descendant of tag 'template'. AMP_HTML_TEMPLATE_PROBLEM
line 46, column 101064
The tag 'template' may not appear as a descendant of tag 'template'. AMP_HTML_TEMPLATE_PROBLEM
line 46, column 102721
amp-access -> amp-access-template -> amp-list -> template
this should work?
Unfortunately, nested templates is blocked on an AMP validation issue. See workarounds here: https://github.com/ampproject/amphtml/blob/master/extensions/amp-mustache/amp-mustache.md#nested-templates
thanks @choumx
Is there a similar functionality to amp-access-template for amp-subscriptions? I want to use the response from authorizationUrl but I cannot get mustache to do it.
/to @jpettitt @chenshay
Most helpful comment
Unfortunately, nested templates is blocked on an AMP validation issue. See workarounds here: https://github.com/ampproject/amphtml/blob/master/extensions/amp-mustache/amp-mustache.md#nested-templates