1

我有一个子组件类型(childComponent),它允许我通过输入参数注入不同的数据。我在这个组件中创建了一个按钮,它打开了一个托管在父组件(应用程序)中的 sidenav 元素。我使用服务架构来实现这一点(settingsService),这部分工作正常。现在我想将另一个组件注入到显示 childComponent 数据的 sidenav (settingComponent) 中。

我为此使用了 ngComponentOutlet 指令,并且 SettingsComponent HTML 正确显示在 sidenav 中,但我不知道如何修改实例的输入变量。我读了一些文章,似乎我需要以某种方式获取 ngComponentOutlet 创建的 ComponentRef 来修改变量,但我不知道如何。我认为这个魔法应该在订阅中的某个地方完成。

应用程序.html

<md-sidenav-container class="sidenav-container">

  <md-sidenav #sidenav class="settings" align="end" mode="over" >
    <ng-container *ngComponentOutlet="settingComponent"></ng-container>
  </md-sidenav>

  <div>
    <a2c-component></a2c-component>
  </div>

  <div>
    // 2nd component (same type with different data)
    <a2c-component></a2c-component>
  </div>

</md-sidenav-container>

应用程序.ts

@Component({
  selector: 'a2c-app',
  template: require('./app.html'),
  viewProviders: [ NgComponentOutlet ]
})
export class AppComponent implements OnInit {

  @ViewChild('sidenav') public settingsBarNavigation: MdSidenav;

  private settingComponent: any;

  constructor(private settingsBarService: SettingsBarService) { }

  public ngOnInit() {
    this.settingsBarService.settingsComponent$.subscribe((_value) => {

        this.settingComponent = _value.component;

        // add settings to new instance here so that
        // <instance of component>.parameterObj.someString = _value.settings.title

        this.settingsBarNavigation.open();
    });
  }
}

设置服务.ts

@Injectable()
export class SettingsBarService {

  public settingsComponent$: Observable<{ component: any, settings: Object}>;
  private settingsComponent: Subject<{ component: any, settings: Object}>;

  constructor() {
    this.settingsComponent = new Subject<{ component: any, settings: Object}>();
    this.settingsComponent$ = this.settingsComponent.asObservable();
  }

  public openSettings(_settingsComponent: any, _settings { title: string, id: number}) {
    this.settingsComponent.next( { component: _settingsComponent, settings: _settings });
  }
}

childComponent.html

<div>
  <button md-button (click)="openSettings()">Open settings</button>
</div>

子组件.ts

@Component({
  selector: 'a2c-component',
  template: require('./childComponent.html')
})
export class ChildComponent {
  private settings: Object;

  constructor(private setBarService: SettingsBarService) {
    // dynamicly filled for each instance of component
    this.settings = { title: 'Hello World!', id: 42 }; 
  }

  // open DynamicLoadedComponent in sideNav
  public openSettings() {
    this.setBarService.openSettings(DynamicLoadedComponent, this.settings);
  }
}

设置组件.html

<div>{{ parameterObj.someString }}</div>

设置组件.ts

@Component({
  selector: 'a2c-dynLoaded',
  template: require('./settingComponent.html')
})
export class DynamicLoadedComponent {

  @Input('parameterObj') public parameterObj: { someString: string };

  constructor() { }
}
4

0 回答 0