Angular 在组件初始化之前加载异步数据
Angular Load Async data before component initialization
我在使用来自 API 调用的数据时遇到问题:我想使用检索到的数据来设置选中复选框,但是组件在 api 响应之前初始化,我得到一些控制台错误:
ERROR TypeError: Cannot read property 'id' of undefined
我也用解析器测试了行为,但我遇到了同样的问题,即使在初始化之前记录了响应数组:
component.ts
...
export class RolesComponent implements OnInit {
flag: boolean = false;
simpleArr: object[] = [
{ userId: 1, id: 2 },
{ userId: 1, id: 3 },
{ userId: 1, id: 5 },
{ userId: 1, id: 7 }
]
permArr: object[] = [];
permArrResolved: object[] = [];
levels = [
{ name: 0, description: 'Creazione nuovo utente' },
{ name: 1, description: 'Reset password di qualsiasi utente' },
{ name: 2, description: 'Eliminazione di qualsiasi utente' },
{ name: 3, description: 'Modifica livello di qualsiasi utente' },
{ name: 4, description: 'Rinnovo delle licenze' },
{ name: 5, description: 'Gestione completa delle licenze' },
{ name: 6, description: 'Gestione completa dei clienti' },
{ name: 7, description: 'Gestione completa dei PC' }
];
constructor(private api: RolesApiService, private route: ActivatedRoute, ) {
this.api.getKeys().subscribe(keys => {
this.permArr = keys;
console.log(this.permArr);
this.flag = true
});
this.route.data.pipe(
map(data => data.cres)).subscribe((key) => {
this.permArrResolved = key;
console.log(this.permArrResolved);
});
}
ngOnInit() {
console.log('component is initialized');
}
}
component.html
<form *ngIf="flag">
<h2>with permArr[0].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === permArr[0]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with simpleArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === simpleArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id using resolver</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArrResolved[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
</form>
我制作了一个 stackblitz 演示来显示错误、api-服务、路由和我使用的解析器。在这里:https://stackblitz.com/edit/async-angular-resolver
我该如何解决这个问题?
编辑:使用安全操作符不能解决该错误
EDIT2:在表单标签中使用 *ngIf 没有解决错误
您可以使用 safe navigation operator: ?.
The Angular safe navigation operator (?.) is a fluent and convenient way to guard against null and undefined values in property paths.
例如:
[checked]="level.name === permArr[0]?.id"
这基本上等同于permArr[0] && permArr[0].id
使用 *ngIf
响应后加载视图:
<form *ngIf="flagpermArr && flagpermpermArrResolved">
<h2>with permArr[0].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === permArr[0]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with simpleArr[level.name].id</h2>
<ng-container *ngFor="let level of levels ; let i = index">
<!-- <input *ngIf="" type="checkbox" [checked]="level.name === simpleArr[level.name].id" />{{level.name}} - {{level.description}}
-->
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id using resolver</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArrResolved[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
</form>
TS:
export class RolesComponent implements OnInit {
flagpermArr: boolean = false;
flagpermpermArrResolved: boolean = false;
simpleArr: object[] = [
{ userId: 1, id: 1 },
{ userId: 1, id: 2 },
{ userId: 1, id: 5 },
{ userId: 1, id: 7 }
]
permArr: object[] = [];
permArrResolved: object[] = [];
levels = [
{ name: 0, description: 'Creazione nuovo utente' },
{ name: 1, description: 'Reset password di qualsiasi utente' },
{ name: 2, description: 'Eliminazione di qualsiasi utente' },
{ name: 3, description: 'Modifica livello di qualsiasi utente' },
{ name: 4, description: 'Rinnovo delle licenze' },
{ name: 5, description: 'Gestione completa delle licenze' },
{ name: 6, description: 'Gestione completa dei clienti' },
{ name: 7, description: 'Gestione completa dei PC' }
];
constructor(private api: RolesApiService, private route: ActivatedRoute, ) {
}
ngOnInit() {
this.api.getKeys().subscribe(keys => {
this.permArr = keys;
this.flagpermArr = true
});
this.route.data.pipe(
map(data => data.cres)).subscribe((key) => {
this.permArrResolved = key;
this.flagpermpermArrResolved = true
});
}
您可以使用:
<ng-container *ngIf="permArr && permArrResolved"> your code here </ng-container>
容器内容只有在 permAr 和 perArrResoved 中有数据时才会呈现。
这里已经有几个答案可以正确回答您提出的问题 - 它们对您不起作用的原因是因为您绑定的数据与您的 ID 不匹配。
你之前的问题基本上都是在问同样的事情:
- angular-nested-ngfor-tags-with-ngif-check-material-data-binding-async-issue
- angular-material-binding-property-does-not-work-cant-bind-to-checked-ngif
为了防止社区进一步浪费精力,我已经开始编写您应该自己编写的调试代码。这显示了安全导航运算符如何修复 模板问题 ,正如一些人已经建议的那样 - 用 *ngIf
包装也可以解决问题,我添加的值说明了原因您的复选框未选中。
https://stackblitz.com/edit/async-angular-resolver-hxxyw4?file=src/app/roles/roles.component.html
我在使用来自 API 调用的数据时遇到问题:我想使用检索到的数据来设置选中复选框,但是组件在 api 响应之前初始化,我得到一些控制台错误:
ERROR TypeError: Cannot read property 'id' of undefined
我也用解析器测试了行为,但我遇到了同样的问题,即使在初始化之前记录了响应数组:
component.ts
...
export class RolesComponent implements OnInit {
flag: boolean = false;
simpleArr: object[] = [
{ userId: 1, id: 2 },
{ userId: 1, id: 3 },
{ userId: 1, id: 5 },
{ userId: 1, id: 7 }
]
permArr: object[] = [];
permArrResolved: object[] = [];
levels = [
{ name: 0, description: 'Creazione nuovo utente' },
{ name: 1, description: 'Reset password di qualsiasi utente' },
{ name: 2, description: 'Eliminazione di qualsiasi utente' },
{ name: 3, description: 'Modifica livello di qualsiasi utente' },
{ name: 4, description: 'Rinnovo delle licenze' },
{ name: 5, description: 'Gestione completa delle licenze' },
{ name: 6, description: 'Gestione completa dei clienti' },
{ name: 7, description: 'Gestione completa dei PC' }
];
constructor(private api: RolesApiService, private route: ActivatedRoute, ) {
this.api.getKeys().subscribe(keys => {
this.permArr = keys;
console.log(this.permArr);
this.flag = true
});
this.route.data.pipe(
map(data => data.cres)).subscribe((key) => {
this.permArrResolved = key;
console.log(this.permArrResolved);
});
}
ngOnInit() {
console.log('component is initialized');
}
}
component.html
<form *ngIf="flag">
<h2>with permArr[0].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === permArr[0]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with simpleArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === simpleArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id using resolver</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArrResolved[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
</form>
我制作了一个 stackblitz 演示来显示错误、api-服务、路由和我使用的解析器。在这里:https://stackblitz.com/edit/async-angular-resolver
我该如何解决这个问题?
编辑:使用安全操作符不能解决该错误 EDIT2:在表单标签中使用 *ngIf 没有解决错误
您可以使用 safe navigation operator: ?.
The Angular safe navigation operator (?.) is a fluent and convenient way to guard against null and undefined values in property paths.
例如:
[checked]="level.name === permArr[0]?.id"
这基本上等同于permArr[0] && permArr[0].id
使用 *ngIf
响应后加载视图:
<form *ngIf="flagpermArr && flagpermpermArrResolved">
<h2>with permArr[0].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name === permArr[0]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with simpleArr[level.name].id</h2>
<ng-container *ngFor="let level of levels ; let i = index">
<!-- <input *ngIf="" type="checkbox" [checked]="level.name === simpleArr[level.name].id" />{{level.name}} - {{level.description}}
-->
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArr[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
<hr>
<h2>with permArr[level.name].id using resolver</h2>
<ng-container *ngFor="let level of levels">
<input type="checkbox" [checked]="level.name == permArrResolved[level.name]?.id" />{{level.name}} - {{level.description}}
<br>
</ng-container>
</form>
TS:
export class RolesComponent implements OnInit {
flagpermArr: boolean = false;
flagpermpermArrResolved: boolean = false;
simpleArr: object[] = [
{ userId: 1, id: 1 },
{ userId: 1, id: 2 },
{ userId: 1, id: 5 },
{ userId: 1, id: 7 }
]
permArr: object[] = [];
permArrResolved: object[] = [];
levels = [
{ name: 0, description: 'Creazione nuovo utente' },
{ name: 1, description: 'Reset password di qualsiasi utente' },
{ name: 2, description: 'Eliminazione di qualsiasi utente' },
{ name: 3, description: 'Modifica livello di qualsiasi utente' },
{ name: 4, description: 'Rinnovo delle licenze' },
{ name: 5, description: 'Gestione completa delle licenze' },
{ name: 6, description: 'Gestione completa dei clienti' },
{ name: 7, description: 'Gestione completa dei PC' }
];
constructor(private api: RolesApiService, private route: ActivatedRoute, ) {
}
ngOnInit() {
this.api.getKeys().subscribe(keys => {
this.permArr = keys;
this.flagpermArr = true
});
this.route.data.pipe(
map(data => data.cres)).subscribe((key) => {
this.permArrResolved = key;
this.flagpermpermArrResolved = true
});
}
您可以使用:
<ng-container *ngIf="permArr && permArrResolved"> your code here </ng-container>
容器内容只有在 permAr 和 perArrResoved 中有数据时才会呈现。
这里已经有几个答案可以正确回答您提出的问题 - 它们对您不起作用的原因是因为您绑定的数据与您的 ID 不匹配。
你之前的问题基本上都是在问同样的事情:
- angular-nested-ngfor-tags-with-ngif-check-material-data-binding-async-issue
- angular-material-binding-property-does-not-work-cant-bind-to-checked-ngif
为了防止社区进一步浪费精力,我已经开始编写您应该自己编写的调试代码。这显示了安全导航运算符如何修复 模板问题 ,正如一些人已经建议的那样 - 用 *ngIf
包装也可以解决问题,我添加的值说明了原因您的复选框未选中。
https://stackblitz.com/edit/async-angular-resolver-hxxyw4?file=src/app/roles/roles.component.html