htlengine icon indicating copy to clipboard operation
htlengine copied to clipboard

feature request: provide current resource path to model and resourceLoader

Open jantimon opened this issue 5 years ago • 4 comments

During runtime resources can be loaded recursively.

Example

For example if we would have the following resource loading:

main.htl 
   -> child.htl
       -> grandchild.htl
       -> grandchild.htl
click here to expand markup example

main.htl

<sly 
  data-sly-resource="${'resourceItem' @ resourceType='child'}"
/>

and in resourceItem you have

child.htl

<sly 
  data-sly-resource="${'childResourceItem1' @ resourceType='grandchild'}"
/>
<sly 
  data-sly-resource="${'childResourceItem2' @ resourceType='grandchild'}"
/>

grandchild.htl

<sly data-sly-use.myModel="com.foo.core.models.myModel"/>
${myModel.title}

Motivation

This resource path information is often used to return the according model data.
In the example above both grandchild.htl could render different data from the same model name.

API

It would be most convenient if the resourcePath could be an array e.g. ['root', 'resourceItem', 'childResourceItem1'] and would be available at two locations:

compiler.withModuleImportGenerator

Although the resourcePath is a runtime only value we could still provide it to the Model mapper e.g.:

compiler.withModuleImportGenerator((baseDir, varName, moduleId) => const ${varName} = function Model() { ...

could be changed to:

compiler.withModuleImportGenerator((baseDir, varName, moduleId) => const ${varName} = function Model(resourcePath) { ...

runtime.withResourceLoader

Inside the runtime it would also be nice to provide this resourceParameter for resource loading:

runtime.withResourceLoader((runtime, resourceName, resourceParameters) => {
runtime.withResourceLoader((runtime, resourceName, resourceParameters, resourcePath) => {

jantimon avatar Jul 27 '20 09:07 jantimon

Sorry, but I don't quite understand. the resource inclusion is done via a resource resolver, which might create a new runtime for the included resource. so it's not really possible to track the hierarchy so easily.

I suggest that the resource resolver implementation should track this accordingly, eg: https://github.com/storybookjs/aem/blob/master/app/aem/src/client/preview/helpers/ResourceResolver.ts#L12

also, there is no way to resolve the resources beforehand, even if they are not dynamic, since the hierarchy of the resources are not know.

tripodsan avatar Sep 25 '20 04:09 tripodsan

@tripodsan you are right it's runtime only.

For the htlengine it is relatively easy to keep track of the current resource path as it can just forward the current resource path to its children and resource loaders.

Both suggested changes are addressing only the runtime api.

jantimon avatar Sep 25 '20 09:09 jantimon

Here is another example which shows why we need not only the current resource id but also its parents:

teasers.sly

<div data-sly-resource="${'teaserItem1' @ resourceType='demo/components/content/teaserItem'}"></div>
<div data-sly-resource="${'teaserItem2' @ resourceType='demo/components/content/teaserItem'}"></div>

teaserItem.sly

<div data-sly-resource="${'image1' @ resourceType='demo/components/content/image'}"></div>
<div data-sly-resource="${'image2' @ resourceType='demo/components/content/image'}"></div>

here a model would have to return different values for teaserItem1 -> image1 teaserItem1 -> image2 teaserItem2 -> image1 teaserItem2 -> image2

jantimon avatar Sep 25 '20 11:09 jantimon

but the (generic) model is instantiated with the content: https://github.com/storybookjs/aem/blob/ddd795d3bf273503e2f21396cb98fd49ad68dc32/app/aem/src/client/preview/helpers/GenericModel.js#L6

and the content is traversed with every resource include: https://github.com/storybookjs/aem/blob/ddd795d3bf273503e2f21396cb98fd49ad68dc32/app/aem/src/client/preview/helpers/ResourceResolver.ts#L33

tripodsan avatar Sep 25 '20 13:09 tripodsan