Может ли объект быть уведомлен, когда объект компонента изменяется в Angular 2/4?
В Angular компонент может получить как @Input()
переменная или объект. Всякий раз, когда переменная изменяется, Angular уведомляет компонент. Очень круто...
Я пытаюсь создать приложение, которое показывает ng2-tree
вид слева и вид редактирования справа. Когда пользователь нажимает на узел в дереве, подробности этого элемента отображаются справа, и пользователь может изменять свойства этого элемента. Что мне нужно, чтобы эти изменения распространились обратно к дереву.
Отдельные узлы в дереве являются ItemTreeNode
:
export class ItemTreeNode implements TreeModel {
value: string;
id: string;
children: Array<ItemTreeNode>;
icon: string;
settings: TreeModelSettings;
loadChildren;
constructor(
private itemService: ItemService,
private parent_id: string,
public item: Item
){ ... }
}
Дерево визуализирует узел, используя .value
для имени. Это устанавливается во время конструктора, вызывая this.item.nodeName()
, После установки оно не меняется. Проблема в том, что он должен меняться всякий раз, когда меняется элемент.
То, что я ищу, - это способ уведомления этого объекта об изменении элемента, чтобы value
свойство может быть обновлено.
Есть ли способ для ItemTreeNode
"наблюдать" за элементом и получать обратный вызов, если он когда-либо изменится, как часть цикла обнаружения изменений Angular?
Или есть лучший способ реализовать желаемое поведение?
1 ответ
Это можно сделать с помощью RxJs. Давайте прервём настройку имени Предмета через сеттер и запустим Observable .next()
,
import {BehaviorSubject} from 'rxjs/BehaviorSubject'
class Item {
private _name: string;
private nameSource = new BehaviorSubject<string>('');
name$ = this.nameSource.asObservable();
set name(name: string) {
this._name = name;
this.nameSource.next(name);
}
get name() { return this._name; }
getNodeName() { return this._name + ' !!!'; }
constructor(name: string){
this._name = name;
}
}
Видите ли, я нажимаю название оригинального предмета на this.nameSource.next(name)
, В моем примере я предполагаю, что имя элемента и имя узла являются разными. наблюдаемый $name
Публично, это для внешних подписок. Затем мне нужно подписаться на изменение имени элемента, и лучшее место для этого - конструктор ItemTreeNode, который получает экземпляр элемента в качестве параметра:
class Node {
value: string;
constructor(item: Item) {
item.name$.subscribe(result => this.value = item.getNodeName());
}
}
Здесь result
это новое имя предмета, но так как оно не совпадает с именем узла предмета, я делаю дополнительный вызов .getNodeName()
, Поэтому единственное, что вам нужно сделать, это передать экземпляр Item конструктору Node, и тогда RxJs выполнит магию привязывания за вас.
this.item = new Item('My Name');
const node = new Node(this.item);
Вот и все, я создал Plunker, чтобы продемонстрировать этот подход.