How to use parent this context in HTML only child view?

I have one parent view and a couple of html only child views. These child views all need to call various functions declared in the parent view.

Is there a way to pass the this context of the parent view to each child, so that they can access these functions?

Please see code below for more info.

PARENT TEMPLATE

<template>
     <require from="../elements/child-01.html"></require>
     <require from="../elements/child-02.html"></require>
     <require from="../elements/child-03.html"></require>

    <div if.bind="showChildOne">
         <child-01></child-01>
    </div>

    <div if.bind="showChildTwo">
         <child-02></child-02>
    </div>

    <div if.bind="showChildThree">
         <child-03></child-03>
    </div>
</template>

CHILD-01 TEMPLATE

<template>
    ...
   <div click.delegate="someFunctionFromParent()">
   </div>
    ...
</template>

CHILD-02 TEMPLATE

<template>
    ...
   <div click.delegate="someFunctionFromParent()">
   </div>
    ...
</template>

CHILD-03 TEMPLATE

<template>
    ...
   <div click.delegate="someFunctionFromParent()">
   </div>
    ...
</template>



One way to go is to do the following:

Parent

<div if.bind="showChildOne">
     <child-01 context.bind="$this"></child-01>
</div>

Chid

<template bindable="context">
    ...
   <div click.delegate="context.someFunctionFromParent()">
   </div>
    ...
</template>

Is there another way to do this?

1 Like

Is this what you want:
https://gist.dumber.app/?gist=9495e66607cf06a3ecc34e5779a6137c&open=src%2Fapp.html

The idea is to use .call binding command to pass the expression specified as a function for later invocation.

Thanks for your answer, but it’s not exactly what I am looking for. So in your example the only thing that get bound into the child view is a function. I would like to know if its possible to allow the html only child to have access to the parent view model (included all methods and properties).

1 Like

You could use dynamic ui composition here (https://aurelia.io/docs/templating/dynamic-ui-composition/)

In short: <compose view="./child1.html"></compose> will compose child1.html with the current binding context.

See gist:
https://gist.dumber.app/?gist=bbff339c67093ff398f8543214ea81c0

2 Likes

By default, all html only element have their binding context (parent view model) assigned to $parent property. The code is here https://github.com/aurelia/templating-resources/blob/5e3af9e7e69bd7c243c917613bea6f0e274e1bf7/src/dynamic-element.ts#L16

So you can call parent methods from child like this: $this.$parent.someMethod(). Example here https://gist.dumber.app/?gist=5a052515305e889fc9bb2bb35c6ea7f9&open=src%2Fchild-01.html

2 Likes

Awesome. Thanks for the help. I think I will try out both and see which fits best.

1 Like

Curious, why do we need to call $this .$parent rather than just $parent? DynamicElement seems to be the implicit viewmodel of the view, so since $parent is a property, should this not always be available? When do and when dont we need to explicitly use $this? Thanks!

2 Likes

In short, it’s an naming choice that was aimed for consistency, but unfortunately confusing.

Normally in Aurelia, an expression starting with $parent in template makes Aurelia binding goes up 1 “level”, in term of scope. This is generally used in repeat/with blocks. Custom element does not have a parent scope that can be traversed normally with $parent.

To compare:
$parent.handleChildClick() means: walk up 1 level of scope (nothing), and call handleChildClick()
$this.$parent.handleChildClick() means: get current scope ($this), access property $parent and then call handleChildClick on that.

2 Likes