Angular2: переменная/функция родительского класса дочернего компонента
У меня есть переменная в родительском компоненте, которая может быть изменена дочерним элементом, родитель будет использовать эту переменную в представлении и, следовательно, должен распространять изменения.
import {Component, View} from 'angular2/core';
@Component({selector: 'parent'})
@View({
directives: [Child],
template: `<childcomp></childcomp>`
})
class Parent {
public sharedList = new Array();
constructor() {
}
}
@Component({selector: 'child'})
@View({template: `...`})
class Child {
constructor() {
//access 'sharedList' from parent and set values
sharedList.push("1");
sharedList.push("2");
sharedList.push("3");
sharedList.push("4");
}
}
Ответы
Ответ 1
Если вы используете привязку данных свойства ввода со ссылочным типом JavaScript (например, Object, Array, Date и т.д.), то родительский и дочерний будут иметь ссылку на один и тот же/один объект. Любые изменения, внесенные в общий объект, будут видны как родителям, так и дочерним.
В родительском шаблоне:
<child [aList]="sharedList"></child>
У ребенка:
@Input() aList;
...
updateList() {
this.aList.push('child');
}
Если вы хотите добавить элементы в список при построении дочернего элемента, используйте ngOnInit()
(а не конструктор(), поскольку свойства данных не инициализированы в этой точке):
ngOnInit() {
this.aList.push('child1')
}
Этот Plunker показывает рабочий пример с кнопками в родительском и дочернем компонентах, которые изменяют общий список.
Обратите внимание, что в случае ребенка вы не должны переназначать ссылку. Например, не делайте этого в дочернем элементе: this.aList = someNewArray;
Если вы это сделаете, то родительский и дочерний компоненты будут иметь ссылки на два разных массива.
Если вы хотите поделиться примитивным типом (т.е. строка, число, логическое), вы можете поместить его в массив или объект (т.е. помещать его внутри ссылочного типа) или вы могли бы emit()
событие от ребенка, когда изменяется примитивное значение (т.е. родительский прослушивает настраиваемое событие, а у ребенка будет свойство вывода EventEmitter
. См. ответ @kit для получения дополнительной информации.)
Обновить 2015/12/22: пример heavy-loader
в Структурные директивы использует технику я представленных выше. Основной/родительский компонент имеет свойство массива logs
, связанное с дочерними компонентами. Детальные компоненты push()
на этот массив, а родительский компонент отображает массив.
Ответ 2
Как насчет небольшого обмана, как NgModel, с NgForm? Вы должны зарегистрировать своего родителя как поставщика, а затем загрузить родителя в конструктор дочернего элемента.
Таким образом, вам не нужно ставить [sharedList]
на всех ваших детей.
// Parent.ts
export var parentProvider = {
provide: Parent,
useExisting: forwardRef(function () { return Parent; })
};
@Component({
moduleId: module.id,
selector: 'parent',
template: '<div><ng-content></ng-content></div>',
providers: [parentProvider]
})
export class Parent {
@Input()
public sharedList = [];
}
// Child.ts
@Component({
moduleId: module.id,
selector: 'child',
template: '<div>child</div>'
})
export class Child {
constructor(private parent: Parent) {
parent.sharedList.push('Me.');
}
}
Затем ваш HTML
<parent [sharedList]="myArray">
<child></child>
<child></child>
</parent>
Ответ 3
В принципе, вы не можете напрямую обращаться к переменным из родителя. Вы делаете это по событиям. За это отвечает свойство вывода компонентов. Я бы предложил прочитать https://angular.io/docs/ts/latest/guide/template-syntax.html#input-and-output-properties
Ответ 4
Вы можете сделать это
В родительском компоненте объявите:
get self(): ParenComponentClass {
return this;
}
В дочернем компоненте после импорта ParenComponentClass объявите:
private _parent: ParenComponentClass ;
@Input() set parent(value: ParenComponentClass ) {
this._parent = value;
}
get parent(): ParenComponentClass {
return this._parent;
}
Затем в шаблоне родителя вы можете сделать
<childselector [parent]="self"></childselector>
Теперь из дочернего объекта вы можете получить доступ к общедоступным свойствам и методам родителя, используя
this.parent
Ответ 5
Основная статья в документации Angular2 по этому вопросу:
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child
Он охватывает следующее:
-
Передача данных от родителя к дочерней с привязкой ввода
-
Переключить свойства ввода с помощью setter
-
Изменение свойств входных данных с помощью ngOnChanges
-
Родитель слушает дочернее событие
-
Родитель взаимодействует с дочерним элементом через локальную переменную
-
Родитель вызывает ViewChild
-
Родитель и дети общаются через службу