Почему не отслеживается обновление моего массива в Ember Octane?

Я пробую Octane, и по какой-то причине, если я показываю массив в шаблоне и добавляю в него новый объект, пользовательский интерфейс не обновляется. Что я делаю неправильно?

Вот мой шаблон:

<label for="new-field-name">Field Name</label>
<Input id="new-field-name" @value={{this.newFieldName}} type="text" />
<button {{on "click" this.addField}}>Add field</button>

{{#each this.fields as |field|}}
    <p>{{field.name}}</p>
{{/each}}

И компонент:

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class ConfigControlsComponent extends Component {
    @tracked fields = []
    @tracked newFieldName = ''

    @action addField() {
        this.fields.push({
            name: this.newFieldName
        })
        console.log(this.fields)
    }
}

console.log показывает массив с новым объектом, добавленным к нему, и fields массив отслеживается, но ничего не меняется, когда я нажимаю кнопку.

2 ответа

Когда вы используете tracked с массивами вам нужно "сбросить" массив, чтобы Ember заметил, что произошли изменения. Попробуй сделать this.fields = this.fields после добавления нового объекта в массив.

export default class ConfigControlsComponent extends Component {
    @tracked fields = []
    @tracked newFieldName = ''

    @action addField() {
        this.fields.push({
            name: this.newFieldName
        })
        this.fields = this.fields // add this line
    }
}

Если вы пытаетесь использовать tracked с объектом вместо массива у вас есть два варианта:

Во-первых, вы можете создать класс, в котором отслеживаются все свойства объекта:

import { tracked } from '@glimmer/tracking';

class Address {
  @tracked street;
  @tracked city;
}

class Person {
  address = new Address();

  get fullAddress() {
    let { street, city } = this.address;

    return `${street}, ${city}`;
  }
}

Или, во-вторых, вы можете использовать тот же подход "сброса", что и в примере с массивом выше.

Массивы не отслеживаются автоматически при изменении одного из их элементов. Вы не можете:

      this.fields.push({
        name: this.newFieldName
    })

Но они отслеживаются, если вы измените весь массив, например, с помощью оператора распространения:

      this.fields = [...this.fields, {name: this.newFieldName}]

Или, в конце концов, вы можете использовать EmberArray , см. Https://guides.emberjs.com/release/in-depth-topics/autotracking-in-depth/#toc_arrays

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