Alexander Mikhalchenko
Alexander Mikhalchenko

Reputation: 4565

Aurelia @children with dynamic data

Suppose I have a custom element in which I iterate over an array of data and render custom subelements.

<my-list action-handler.bind="actionHandler">
  <my-element item.bind="element" repeat.for="element of data"></my-element>
</my-list>

In my-list.html I render the contents with <contents></contents> and in general the real code is a bit more complex and has replaceable template parts, but that's not the problem.

I want the actionHandler that I bind to MyList to be available in all of the children. For the sake of elegancy, we did this in my-list.js:

@children('*:not(div)') listItems;

//...
attached(){
    this.listItems.forEach((e) => {
        e.actionHandler = this.actionHandler;
    });
}

And everything worked just fine until we started to load data dynamically. In this case listItems is empty since the element is initialized before the child elements re-rendered.

So, the question is:

How would I make @children be re-calculated?

I understand that we could bind the actionHandler to all children when we were repeating over them, but this would start to look really ugly when we add some more logic like

Thanks!

Upvotes: 0

Views: 1406

Answers (2)

kabaehr
kabaehr

Reputation: 1040

The Aurelia Cheat Sheet is telling that:

@children(selector) - Decorates a property to create an array on your class that has its items automatically synchronized based on a query selector against the element's immediate child content.

so i guess it is not possible to use @children with dynamic data.

You might should go with the Parent approach, like the previous answer is suggesting.

Upvotes: 1

Jeremy Danyow
Jeremy Danyow

Reputation: 26406

If <my-element> has a dependency on it's parent <my-list> element's actionHandler, you can express that declaratively and let Aurelia's dependency injection system do the rest. Here's a couple of ways to do that...

If <my-element> will always be within a <my-list> (doesn't necessarily need to be directly within):

import {inject} from 'aurelia-dependency-injection';

@inject(MyList)
export class MyElement {
  constructor(list) {
    this.actionHandler = list.actionHandler;
  }
}

If you need access <my-element>'s closest parent custom element, regardless of what it is:

import {inject, Parent} from 'aurelia-dependency-injection';

@inject(Parent.of(Element))
export class MyElement {
  constructor(parent) {
    this.actionHandler = parent.actionHandler;
  }
}

I know this wasn't exactly what you were asking but I'm proposing this in case it's a simpler way to meet your requirements.

Upvotes: 2

Related Questions