SrA*_*Axi 24 typescript angular
所以,我有一个使用这个模板动态呈现几个组件的组件:
<div [saJquiAccordion]="{active: group.value['collapsed']}" *ngFor="let group of filterGroupsTemplate | keysCheckDisplay;">
<div>
<h4>{{group.key | i18n}}</h4>
<form id="ibo-{{group.key}}" class="form-horizontal" autocomplete="off" style="overflow: initial">
<fieldset *ngFor="let field of group.value | keys">
<ng-container *ngComponentOutlet="fieldSets[field.value.template];
ngModuleFactory: smartadminFormsModule;"></ng-container>
</fieldset>
</form>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
问题是填充那些我从API调用中获取它的组件所需的数据:
this.getFiltersSubscription = this.getFilters().subscribe(
(filters) => {
this.filters = filters;
log.info('API CALL. getting filters');
// Sending data to fieldform components
this.iboService.updateIBOsRankList(filters['iboRank'].data);
this.iboService.updateIBOsNewsletterOptions(filters['iboNewsletter'].data);
this.iboService.updateIBOsTotalOrders(filters['iboTotalOrders'].data);
}
);
Run Code Online (Sandbox Code Playgroud)
因此,一旦我获得了数据,我就会触发我的组件订阅的服务Observable,然后他们将处理收集的数据.
问题:
如果在所有组件加载之前进行API调用,我将触发这些服务方法传递数据,但没有人会订阅这些Observable.
一种方法是:
首先加载数据,只有当我加载了数据时,我才会渲染模板,因此动态渲染所有这些组件,然后才会触发这些服务方法(Observables).
我不想为每个组件进行API调用,因为它可能像60个组件,我宁愿松散代码的抽象,但我喜欢做这样的事情:
// Listens to field's init and creates the fieldset triggering a service call that will be listened by the field component
this.iboService.initIBOsFilters$.subscribe(
(fieldName) => {
if (fieldName === 'IBOsRankSelectorFieldComponent') {
log.data('inside initIBOsFilters$ subscription, calling updateIBOsFilters()', fieldName);
this.iboService.updateIBOsRankList(this.filters['iboRank'].data); // HERE I'M PASSING DATA TO THE COMPONENT RENDERED DYNAMICALY. BUT IF this.filters IS UNDEFINED, IT BREAKS
}
}
);
Run Code Online (Sandbox Code Playgroud)
为了做到这一点,我需要确保this.filters定义,因此,我得出结论:
我怎么能等到API调用结束并this.filters在渲染我的模板html之前定义?
对不起,如果我的问题有点长,如果您需要更多详细信息,请告诉我.
谢谢!
SrA*_*Axi 33
在研究了人们给我的不同方法后,我在async管道上找到了解决方案.但是,我花了一些时间来了解如何实现它.
解:
// Declaring the Promise, yes! Promise!
filtersLoaded: Promise<boolean>;
// Later in the Component, where I gather the data, I set the resolve() of the Promise
this.getFiltersSubscription = this.getFilters().subscribe(
(filters) => {
this.filters = filters;
log.info('API CALL. getting filters');
this.filtersLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data
}
);
// In this listener triggered by the dynamic components when instanced,
// I pass the data, knowing that is defined because of the template change
// Listens to field's init and creates the fieldset triggering a service call
// that will be listened by the field component
this.iboService.initIBOsFilters$.subscribe(
(fieldName) => {
if (fieldName === 'IBOsRankSelectorFieldComponent') {
log.data('inside initIBOsFilters$ subscription, calling updateIBOsFilters()', fieldName);
this.iboService.updateIBOsRankList(this.filters['iboRank'].data);
}
}
);
Run Code Online (Sandbox Code Playgroud)
在模板中,我使用async需要a Observable或a 的管道Promise
<div *ngIf="filtersLoaded | async">
<div [saJquiAccordion]="{active: group.value['collapsed']}" *ngFor="let group of filterGroupsTemplate | keysCheckDisplay;">
<div>
<h4>{{group.key | i18n}}</h4>
<form id="ibo-{{group.key}}" class="form-horizontal" autocomplete="off" style="overflow: initial">
<fieldset *ngFor="let field of group.value | keys">
<ng-container *ngComponentOutlet="fieldSets[field.value.template];
ngModuleFactory: smartadminFormsModule;"></ng-container>
</fieldset>
</form>
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
注意:
async管道需要一个Observable或一个Promise我所理解的,这就是为什么使其工作的唯一方法是创建一个Promiseresolver方法,因为当你通过Angular的路由到达组件时会使用它.此组件是较大组件的一部分,并且不像任何其他正常组件那样通过路由实例化.(尽管尝试过这种方法,但有点工作,没有完成这项工作)您可以使用a resolver来确保在激活路由之前加载这些数据(或者已初始化过滤器).
https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html
https://angular.io/api/router/Resolve
<p class="p-large">{{homeData?.meta[0].site_desc}}</p>
Run Code Online (Sandbox Code Playgroud)
只是用了一个“?” 在从服务器加载数据的变量之后。
home.component.ts
import { Component, OnInit } from '@angular/core';
import { HomeService } from '../services/home.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
public homeData: any;
constructor(private homeService: HomeService) {}
ngOnInit(): void {
this.homeService.getHomeData().subscribe( data => {
this.homeData = data[0];
}, error => {
console.log(error);
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
53257 次 |
| 最近记录: |