Как получить родительский контекст из компонента в glimmer?

Допустим, у меня есть простой компонент в glimmer со списком элементов

<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?
  }
}

Даже если я передаю в действие от родителя

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

обновлено, template.hbs

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

в моем внешнем компоненте.тс

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

Я пытаюсь создать компонент со списком. Когда щелкают элемент списка, я хочу, чтобы он всплывал вверху события щелчка, чтобы родительский компонент мог принять решение скрыть список и показать более подробный вид для этого выбранного элемента.

Как мне сделать это в мерцании? В ответ я бы пройти

Примечание: я не использую полный ember.js, только автономный glimmer.js

2 ответа

Решение

Из-за вашего комментария, что у вас есть доступ только к тому, что находится в теле функции, я подозреваю, что action помощник при привязке действия к дочернему компоненту заставляет обратный вызов потерять this,

Чтобы решить эту проблему, свяжите это так:

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

Я сделал пример детской площадки, которую вы можете проверить.

Что-то, чему я научился в React, также работает в моем приложении Glimmer: вы можете связывать свои функции в конструкторе. Таким образом, когда вы передаете их разным объектам, они не теряют свой контекст.

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

Теперь вы можете передать эту функцию напрямую, как раньше, без использования дополнительных action помощник.

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

затем...

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

При нажатии консоль будет регистрироваться true потому что функция все еще вызывается в контексте родительского класса.

Другие вопросы по тегам