The .ts file of my Aurelia component generates arrays of composed elements to render :
private getComposedElements(panelIndex: number): ComposedElement[] {
return this.panels[panelIndex].map(element => toComposedElement(element));
}
In an ideal world, the .html then would render them like this :
<template repeat.for="item of getComposedElements(0)">
<compose containerless view-model.bind="item">
</compose>
</template>
<!-- All elements of panel 1 -->
<template repeat.for="item of getComposedElements(1)">
<compose containerless view-model.bind="item">
</compose>
</template>
<!-- All elements of panel 2 -->
<template repeat.for="item of getComposedElements(2)">
<compose containerless view-model.bind="item">
</compose>
</template>
...
(note that I could also have used a repeat.for
for all panels in an outer loop, but I wanted to ask my question in a more readable manner)
Problem : the code above doesn’t work, because I need the render to be recomputed when this.panels
changes. Normally I would simply add @computedFrom
just above getComposedElements
but it doesn’t work because that annotation only works with getters
(i.e. : no ‘panelIndex
‘ parameter allowed!)
So instead I did this :
@computedFrom("panels") // or panels.length if that makes you sleep better
public get getComposedElements0(): ComposedElement[] {
return this.getComposedElements(0);
}
@computedFrom("panels")
public get getComposedElements1(): ComposedElement[] {
return this.getComposedElements(0);
}
private getComposedElements(panelIndex: number): ComposedElement[] {
return this.panels[panelIndex].map(element => toComposedElement(element));
}
.html
<!-- All elements of panel 0 -->
<template repeat.for="item of getComposedElements0">
<compose containerless view-model.bind="item">
</compose>
</template>
<!-- All elements of panel 1 -->
<template repeat.for="item of getComposedElements1">
<compose containerless view-model.bind="item">
</compose>
</template>
...
It works but it is horrible. It would be insane to create as many getComposedElementsXXX getters as there are panels.
I thought the simplest solution might be to get rid of method getComposedElements
entirely and instead do something like this, directly in the .html
:
<template repeat.for="item of panels[0].map(element => toComposedElement(element))">
<compose containerless view-model.bind="item">
</compose>
</template>
<template repeat.for="item of panels[1].map(element => toComposedElement(element))">
<compose containerless view-model.bind="item">
</compose>
</template>
...
Sadly, Aurelia does not allow complex syntax inside repeat.for. The compiler complains about =>
or other symbols like !!
or whatnot.
So what’s the solution here? If I start making the panels composed components too, then the amount of boilerplate code will explode to pass bindables up and down. Plus, I will probably fail as I barely understand what I’m doing with Aurelia.