简体   繁体   中英

How do I get the parent context from within a component in glimmer?

Let's say I have a simple component in glimmer with a list of items

<todo-list @items={{ items }}></todo-list>

template.hbs

<ul>
  {{#each @items key="@index" as |item|}}
    <li onclick={{ action clickme }}>{{ item }}</li>
  {{/each}}
</ul>

component.ts

import Component, { tracked }  from '@glimmer/component';

export default class TodoList extends Component {
  constructor(options) {
    super(options);
  }
  clickme() {
     // how do I access the parent context from here?
  }
}

Even if I pass in an action from the parent

<todo-list @items={{ items }} @rootclickme={{ rootclickme }}></todo-list>

updated, template.hbs

<ul>
  {{#each @items key="@index" as |item|}}
    <li onclick={{ action @rootclickme }}>{{ item }}</li>
  {{/each}}
</ul>

in my outer component.ts

rootclickme () {
    // I don't have access to parent variables here either?
    // only what's within the scope of the function itself?         
}

What I'm trying to do is have a component with a list. When a list item is clicked, I want it to bubble up a click event to the top, so that the parent component can decide to hide the list and show a more detailed view for this selected item.

How do I go about doing this in glimmer? In react I'd be passing

Note: I'm not using full ember.js, just glimmer.js standalone

By your comment that you only have access to what's in the function body, my suspicion is that the missing action helper when binding the action to the child component is making the callback lose its this .

To address it, bind it in like this:

<todo-list @items={{ items }} @rootclickme={{action rootclickme}}></todo-list>

I have made an example playground that you can check out.

Something I learned from React, that works in my Glimmer app as well: you can bind your functions in the constructor. That way, when you pass them around to different objects, they won't lose their context.

export default class WhateverRootComponent extends Component {
  constructor(options) {
    super(options);
    this.rootClickMe = this.rootClickMe.bind(this)
  }
  rootClickMe() {
    console.log(this instanceof WhateverRootComponent)
  }
}

Now you can pass that function in directly as you were doing before, without using the extra action helper.

<!-- WhateverRootComponent template -->
<SomeChild @actionToTake={{ rootClickMe }} />

then...

<!-- SomeChild template -->
<button onclick={{ action @actionToTake }}> Click Me </button>

When clicked, the console will log true because the function still is being called in the parent class's context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM