最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular Load Async data before component initialization - Stack Overflow

programmeradmin3浏览0评论

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 badges
Add a ment  | 

4 Answers 4

Reset to default 4

There 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.

发布评论

评论列表(0)

  1. 暂无评论