Подтвердить что ты не робот

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');
  }
}

Здесь - это плункер, который поможет вам понять мой вопрос:

4b9b3361

Ответ 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;
    });
}