I have a problem to use data from API Calls: I want to use the retrieved data to set checked in a checkbox, but the ponent is initialized before the api response and I get some console error:
ERROR TypeError: Cannot read property 'id' of undefined
I test the behaviour with a resolver too, but I have the same problem, even if the response array is logged before initialization:
ponent.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 pleta delle licenze' },
{ name: 6, description: 'Gestione pleta dei clienti' },
{ name: 7, description: 'Gestione pleta 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('ponent is initialized');
}
}
ponent.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>
I've made a stackblitz demo to show the error, the api-service, the routing and the resolver I use. is here:
How can I solve this problem?
EDIT: using safe oprators do not solve the bug EDIT2: using *ngIf in form tag do not solve the bug
I have a problem to use data from API Calls: I want to use the retrieved data to set checked in a checkbox, but the ponent is initialized before the api response and I get some console error:
ERROR TypeError: Cannot read property 'id' of undefined
I test the behaviour with a resolver too, but I have the same problem, even if the response array is logged before initialization:
ponent.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 pleta delle licenze' },
{ name: 6, description: 'Gestione pleta dei clienti' },
{ name: 7, description: 'Gestione pleta 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('ponent is initialized');
}
}
ponent.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>
I've made a stackblitz demo to show the error, the api-service, the routing and the resolver I use. is here: https://stackblitz./edit/async-angular-resolver
How can I solve this problem?
EDIT: using safe oprators do not solve the bug EDIT2: using *ngIf in form tag do not solve the bug
Share Improve this question edited Aug 2, 2018 at 9:36 ufollettu asked Aug 2, 2018 at 9:06 ufollettuufollettu 8823 gold badges20 silver badges48 bronze badges4 Answers
Reset to default 4There are already several answers here that correctly answer the question you are asking - the reason they dont work for you is because the data you are binding does not matching your ids.
Your previous questions were both basically asking the same thing:
- angular-nested-ngfor-tags-with-ngif-check-material-data-binding-async-issue
- angular-material-binding-property-does-not-work-cant-bind-to-checked-ngif
To prevent further wasted effort from the munity, I've gone to the effort of writing the debug code you should be writing yourself. This shows how the safe navigation operator fixes the template issue, as several people have suggested already - wrapping with *ngIf
would also solve the problem and the values I've added show why your tick boxes are not checked.
https://stackblitz./edit/async-angular-resolver-hxxyw4?file=src/app/roles/roles.ponent.html
You can use the safe navigation operator: ?.
The Angular safe navigation operator (?.) is a fluent and convenient way to guard against null and undefined values in property paths.
For example:
[checked]="level.name === permArr[0]?.id"
This is essentially equivalent to permArr[0] && permArr[0].id
Load View after response using *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 pleta delle licenze' },
{ name: 6, description: 'Gestione pleta dei clienti' },
{ name: 7, description: 'Gestione pleta 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
});
}
You could use:
<ng-container *ngIf="permArr && permArrResolved"> your code here </ng-container>
The containers content will only be rendered when permArr and perArrResoved have data in them.