简体   繁体   English

如何从 Observable 向子组件的 @Input 传递数据

[英]How to pass data to child component's @Input from Observable

I have an angular component that I use as a tab in a for loop on the html page:我有一个 angular 组件,用作 html 页面上 for 循环中的选项卡:

...
<ng-container *ngFor="let tabData of data$ | async;">
  <tab-component
   id="{{ tabData.id }}"
   name="{{ tabData.name }}"
  >
  </tab-component>
</ng-container>
<child-component [selectedData]="selectedData"></child-component>

And in the.ts file:在 .ts 文件中:

public data$: Observable<Data[]>
public selectedData: Data

ngOnInit() {
  this.data$ = this.service.getAllData();
}
ngAfterContentInit() {
  this.data$.subscribe(items => this.selectedData = items[0])
}

I would like the first tab to always be the selectedData by default when first loading the page (element 0 in the array).我希望第一个选项卡在第一次加载页面(数组中的元素 0)时默认始终是 selectedData。 Then on click or the right/left arrow keys, dynamically update the value of selectedData passed to the child component.然后单击或右/左箭头键,动态更新传递给子组件的 selectedData 的值。 So far, I've tried everything and the value of selectedData in the child component has always been undefined到目前为止,我已经尝试了所有方法,并且子组件中 selectedData 的值始终未定义

Please help me, how can I achieve this!请帮助我,我怎样才能做到这一点!

  1. Subscribe for allData in the ngOnInIt itself and do check the value of items before assigning it - whether you are getting it or not and if you are not able to find the value there, then there must be the issue with the getAllDataService .ngOnInIt本身中订阅 allData 并在分配它之前检查items的值 - 无论你是否得到它,如果你无法在那里找到值,那么getAllDataService一定有问题。
  2. For child component, use double quotes to pass the value like this: <child-component [selectedTab]="selectedTab"></child-component>对于子组件,使用双引号传递这样的值: <child-component [selectedTab]="selectedTab"></child-component>
  3. Create a dummy variable in the parent ( or a hardcoded value ) and pass it to child.在父级(或硬编码值)中创建一个虚拟变量并将其传递给子级。 If your child component is working fine, then there's issue with only data and how you are assigning it.如果您的子组件工作正常,那么只有数据以及您如何分配数据存在问题。

Hope this helps!希望这可以帮助!

Where exactly are you using the selectedData in your template HTML file?您在模板 HTML 文件中究竟在哪里使用selectedData

In the snippet you provided there is a selectedTab used, but no selectedData anywhere...在您提供的片段中,使用了一个selectedTab ,但在任何地方都没有selectedData ...

<ng-container *ngFor="let tabData of data$ | async;">
  <tab-component
   id="{{ tabData.id }}"
   name="{{ tabData.name }}"
  >
  </tab-component>
</ng-container>
<child-component [selectedTab]=selectedTab></child-component>

Also, you can follow @Eugene's advice and do:此外,您可以遵循@Eugene 的建议并执行以下操作:

ngOnInit() {
   this.data$ = this.service.getAllData().pipe(
      tap((items) => this.selectedData = items[0])
   );
}

without using ngAfterContentInit() and the need to subscribe a second time.不使用ngAfterContentInit()并且需要第二次订阅。

You could use a subject to express the currently selected tab data, then use combineLatest to create an observable of both sources.您可以使用主题来表达当前选择的选项卡数据,然后使用combineLatest创建两个来源的 observable。

private data$: Observable<Data[]> = this.service.getAllData();
private selectedData$ = new BehaviorSubject<Data>(undefined);

vm$ = combineLatest([this.data$, this.selectedData$]).pipe(
    map(([tabData, selected]) => ({
        tabData,
        selectedTab: selected ?? tabData[0]
    })
);

setSelected(data: Data) {
  this.selectedData$.next(data);
}

Here we create a single observable that the view can use ( a view model ) using combineLatest .在这里,我们使用combineLatest创建视图可以使用的单个 observable(视图 model )。 This observable will emit whenever either of its sources emit.每当它的任何一个源发出时,这个 observable 都会发出。

We set the selectedData$ BehaviorSubject to emit an initial value of undefined .我们将selectedData$ BehaviorSubject设置为发出undefined的初始值。 Then, inside the map, we set the selectedTab property to use tabData[0] when selected is not yet set.然后,在 map 内部,我们将selectedTab属性设置为在尚未设置选择时使用tabData[0] So, initially, it will use tabData[0] , but after setSelected() gets called, it will use that value.因此,最初,它将使用tabData[0] ,但在setSelected()之后,它将使用该值。

<ng-container *ngIf="let vm$ | async as vm">

  <tab-component *ngFor="let tabData of vm.tabData"
    [id]    = "tabData.id"
    [name]  = "tabData.name"
    (click) = "setSelected(tabData)">
  </tab-component>

  <child-component [selectedTab]="vm.selectedTab"></child-component>

</ng-container>

I managed to get it so that the passed value on the child side is no longer undefined with an ngIf, so:我设法得到它,以便在子端传递的值不再使用 ngIf 未定义,所以:

<child-component *ngIf=selectedData [selectedData]="selectedData"></child-component>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM