Angular2: двусторонняя привязка данных к компоненту, динамически вставленному с помощью DynamicComponentLoader
Я разрабатываю приложение Angular2, и у меня возникла проблема:
У меня есть набор различных объектов, которые можно выбрать с помощью пользовательского интерфейса. Каждый из этих объектов имеет набор параметров (разных для разных объектов), которые можно редактировать с помощью пользовательского интерфейса. Теперь я использую DynamicComponentLoader для вставки определенного компонента для выбранного в данный момент объекта, поэтому он может корректно обрабатывать его параметры.
Проблема в том, что я не знаю, как привязывать данные текущего выбранного объекта к динамически вставленному компоненту параметров.
@Component({
selector: 'dynamic',
template: `<div>Options:</div>
<div>Property1: <input type="number" /></div>
<div>Property2: <input type="text" /></div>`
// template: `<div>Options:</div>
// <div>Property1: <input type="number" [(ng-model)]="currentSelection.property1" /></div>
// <div>Property2: <input type="text" [(ng-model)]="currentSelection.property1" /></div>`
})
class DynamicComponent {
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Selected: {{currentSelection.name}}!</h2>
<div #container></div>
</div>
`
})
class App {
currentSelection = {name: 'Selection1', property1: 10, property2: 'test'};
constructor(private loader: DynamicComponentLoader, private elementRef: ElementRef) {
loader.loadIntoLocation(DynamicComponent, elementRef, 'container');
}
}
Здесь - это плункер, который поможет вам понять мой вопрос:
Ответы
Ответ 1
С angular2 и Rxjs " Observables - это почти всегда ответ.
Если я правильно понял вашу проблему, вам нужно сделать DynamicComponent " Observer" и ваш контейнер "a Observable или даже лучше Subject (если ваш контейнер нужен подписываться на другую, наблюдаемую для получения выборов). Затем, после загрузки динамического компонента, подпишите его в свой контейнер.
Всякий раз, когда выбор изменяется на вашем контейнере, вы нажимаете новый выбор своим подписчикам. Таким образом, вы можете загружать несколько динамических компонентов, и все получат ваши нажатия.
Контейнер:
class App {
currentSelection = {};
selections = [
{name: 'Selection1', property1: 10, property2: 'test'},
{name: 'Selection2', property1: 20, property2: 'test2'}
];
subject:Subject<any> = new Subject();
constructor(private loader: DynamicComponentLoader, private elementRef: ElementRef) {
}
ngOnInit(){
this.loader.loadIntoLocation(DynamicComponent, this.elementRef, 'container', this.injector)
.then(compRef =>this.subject.subscribe(compRef.instance));
// subscribe after loading the dynamicComponent
}
// set the new selection and push it to subscribers
changeSelection(newSelection){
this.currentSelection = newSelection;
this.subject.next(this.currentSelection);
}
}
Наблюдатель:
class DynamicComponent implements Observer{
public currentSelection = {};
next(newSelection){
this.currentSelection = newSelection;
}
}
Вот ваш plunker, работающий после моих изменений, "при условии, что я изменил импорт на новейшую angular beta.6"
Я знаю, что это довольно старый вопрос. Но, надеюсь, кто-то выиграет от этого ответа.
Ответ 2
Вот что вы можете сделать, переместите код от constructor
до ngOnInit
и используйте promises для назначения динамического значения.
ngOnInit(){
this.dynamicComponentLoader.loadIntoLocation(DynamicComponent, this.elementRef,'container').then((component)=>{
component.instance.currentSelection = currentSelection;
});
}