【问题标题】:Angular Load Async data before component initialization在组件初始化之前角加载异步数据
【发布时间】:2018-08-02 09:06:18
【问题描述】:

我在使用来自 API 调用的数据时遇到问题:我想使用检索到的数据来设置复选框中的选中状态,但是组件在 api 响应之前被初始化并且我收到了一些控制台错误:

错误类型错误:无法读取未定义的属性“id”

我也使用解析器测试行为,但我遇到了同样的问题,即使响应数组在初始化之前记录:

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 不能解决错误

【问题讨论】:

    标签: javascript angular asynchronous service angular-resolver


    【解决方案1】:

    这里已经有几个答案可以正确回答您提出的问题 - 它们不适合您的原因是因为您绑定的数据与您的 id 不匹配。

    你之前的问题基本上都是问同一个问题:

    为了防止社区进一步浪费精力,我已经开始编写您应该自己编写的调试代码。这显示了安全导航操作员如何修复 模板问题,正如一些人已经建议的那样 - 用 *ngIf 包装也可以解决问题,我添加的值显示了为什么你的复选框没有检查。

    https://stackblitz.com/edit/async-angular-resolver-hxxyw4?file=src/app/roles/roles.component.html

    【讨论】:

    • 谢谢,我修改了很多代码来实现我的目的,但现在可以了
    【解决方案2】:

    您可以使用safe navigation operator?.

    Angular 安全导航运算符 (?.) 是防止属性路径中出现空值和未定义值的一种流畅且方便的方法。

    例如:

    [checked]="level.name === permArr[0]?.id"
    

    这基本上等同于permArr[0] &amp;&amp; permArr[0].id

    【讨论】:

    • 我试过了,但这并不能解决第二个循环中的问题:如果我设置level.name == permArr[level.name]?.id我没有选中复选框
    【解决方案3】:

    使用*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
          });
      }
    

    【讨论】:

    • 我试过了,但没有用...我更新了stackblitz,请检查是否可以
    • 好的,所以在你的代码中,'simpleArr' 长度是 4,而 'levels' 是 8,这就是为什么没有索引来获取 'simpleArr[level.name]'。只看评论部分
    • 我希望你能理解。没有什么关于响应的,你只需要维护正确的数组
    【解决方案4】:

    你可以使用:

    <ng-container *ngIf="permArr && permArrResolved"> your code here </ng-container>
    

    只有当 permArr 和 perArrResoved 中有数据时才会呈现容器内容。

    【讨论】:

    • permArr 和 permArrResolved 仅用于测试目的,我只需要其中一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    • 2018-09-05
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多