Au-render and bindings in Aurelia 2

I have been experimenting with au-render and au-compose. From what I understand, it is still work in progress. I have stumbled upon au-render’s ability to compose element using string as name.

<au-render component="my-component"></au-render>

Is it possible to bind to component’s properties in this use-case ? I have tried, but to no avail.

1 Like

Ensure that you have registered the custom element. Refer the tests here: https://github.com/aurelia/aurelia/blob/master/packages/__tests__/3-runtime-html/au-render.spec.ts#L201-L209

1 Like

Thanx for fast response.
I already made sure that component is registered. I am able to render the component. However, I cannot pass model to it. I am trying to use it for dynamic composition. I am creating a menu tree. I have different components representing different types of menu items. They all have @bindable property model. Then I have something like this:

<div class="some-menu-container">
  <au-render repeat.for="item of tree.items" component.bind="item.type" model.bind="item"></au-render>
<--Or-->
 <au-render repeat.for="item of tree.items" component="${item.type}" model.bind="item"></au-render>
            </div>

Both variants render the component, but model remains undefined. (Checking it via attached())
I could not find any model binding examples in tests, and am unsure if model binding in this use-case is supported at all.

1 Like

AFAIK au-render does not take any bindable model. I think you need to use the au-compose for that. You can find the docs for that here: Dynamic composition - The Aurelia Docs.

cc: @bigopon

1 Like

I tried that first and could not make it work in any way remotely as simple as in au1.
Closest I came to a solution is to assign “component type” to a variable in root model, and then using view-model.bind=“MyComponent”.
This works when used with activate method to pass model in component:

  <au-compose view-model.bind = "MenuItemClass" model.bind="{ model: {name:'test'}}" ></au-compose>

But using a string variable componentNameAsStringVariable = “MenuItemClass” in model-view.bind does not.

<au-compose view-model.bind = "componentNameAsStringVariable" model.bind="{ model: {name:'test'}}" ></au-compose>
<--NOR-->
 <au-compose view-model.bind = "${componentNameAsStringVariable}" model.bind="{ model: {name:'test'}}" ></au-compose>

So my question is:
Is it possible to dynamically compose components by providing component name as string to “au-compose” in any way, without resorting to a ValueConverter solution.

Also, composing views stored as .html files with an access to parent scope would work too, but I don’t see how would I accomplish that with “au-compose” at the moment.

1 Like

In v1, it works like this:
if view-model is:

  • a string, it’s a module path, load the module, get the real view model class then compose
  • a class, it’s the real view model class, now compose

the part “load the module” is what makes it simple, but it’s also quite costly: it involves quite a complex module resolution at runtime, that is in parts different with build time module resolution.

In v2, we don’t want to take the string feature over, and it now works like this:
if view-model is:

  • a class, it’s the real view model class, now compose
  • an object, it’s the real view model instance, now compose
  • a promise, it’s a promise that resolves to either of the above, now compose

So while the ability to load from a string is dropped, it’s actually better now with the ability to understand promise. As you can see from this example:

<au-compose view="https://my-server.com/views/${componentName} | loadView">
class LoadViewValueConverter {
  toView(v) { return fetch(v).then(r => r.text()) }
}

:point_up_2: to me, this is as flexible as v1, more powerful, a bit more boilerplate-y though a lot easier for readability.

You can find out more details from the PR here https://github.com/aurelia/aurelia/pull/1184

3 Likes

Thank you. It makes sense. Will adjust mindset accordingly.

1 Like