Search code examples
javascriptrepeaterparentaureliacustom-element

Get correct context from child custom element which displays in repeater loop. Aurelia


I have parent template which has a repeater for child custom elements.

<!-- users.html -->
<div class="col-sm-6 col-md-3" repeat.for="user of users">
    <git-hub-user-card user.bind="user" edit-user.bind="editUser"></git-hub-user-card>
</div>

editUser is callback located in parent VM and i need to call it from my child custom element.

Here is my child custom component

/*user.js*/
import {customElement, bindable} from 'aurelia-framework';

    @customElement('git-hub-user-card')
    export class GithubUser {

        @bindable editUser;
        @bindable user = {};

        bind(parentCtx) {
            this.$parentCtx = parentCtx;
        }
    }

and here is child template

<!-- user.html -->
<div class="content">
   <p class="name" >${user.login}</p>
   <a href="#" class="btn btn-default" click.delegate="editUser.call($parentCtx, $event, user)">Edit Name</a>
 </div>

So, i have passed callback function in child component by binding.

<git-hub-user-card user.bind="user" edit-user.bind="editUser"></git-hub-user-card>

My first question: is it ok? Or there is some more neat approach to call callback from child component?

Then i have tried to get parent VM context in the child VM:

bind(parentCtx) {
  this.$parentCtx = parentCtx;
}

and have tried to bound callback call to this context:

<a click.delegate="editUser.call($parentCtx, $event, user)">Edit Name</a>

but $parentCtx is not correct in this case because of repeat.for in parent template. $parentCtx is equal to my GithubUser. How can i get the correct context for editUser in parent VM? Should i path it with bounding?


Solution

  • Use the call binding command in the users.html template. It will preserve the correct context/this when the method is invoked. Here's what that would look like:

    user.js

    import {customElement, bindable} from 'aurelia-framework';
    
    @customElement('git-hub-user-card')
    export class GithubUser {
      @bindable editUser;
      @bindable user;
    }
    

    user.html

    <div class="content">
      <p class="name" >${user.login}</p>
      <a href="#" class="btn btn-default" click.delegate="editUser()">Edit Name</a>
    </div>
    

    users.html

    <div class="col-sm-6 col-md-3" repeat.for="user of users">
      <git-hub-user-card user.bind="user" edit-user.call="editUser(user)"></git-hub-user-card>
    </div>