【问题标题】:How can I avoid using *ngIf in an Angular template?如何避免在 Angular 模板中使用 *ngIf?
【发布时间】:2020-05-30 10:21:32
【问题描述】:

我尝试使用 async/await 来避免组件模板中出现*ngIf

当我在组件模板中删除 *ngIf 时,Chrome 控制台出现错误。

任何人都可以帮助获得解决方案。我不想在组件模板中使用*ngIf 作为要求

我正在调用 GET REST API 并使用订阅。此外,如果我使用*ngIf,我会得到没有错误的结果,但我想要不使用*ngIf 的相同结果

代码: 组件.ts

export class DisplayComponent implements OnInit {
users : user[];
user: user;
userResult: any;

  constructor(private http: HttpClient) { }

  ngOnInit() {
  }


  async readUser(id){
     this.userResult = await this.http.get<user>("http://localhost:8090/user/" +id).subscribe(
       data => {
         this.user = data;
       },
       error =>{
         return console.error();
         ;
       }
     )
    console.log("Fuuhhh! Client will wait till promise is resolved.");
  }
}

代码: DisplayComponent.html

<div style="text-align: center;">
    <button (click)="loadUsers()">load Users</button>
    <table style="margin: 0 auto;" border="1">
        <tr>
            <th>Identity</th>
        </tr>
        <tr *ngFor="let user of users">
           <td>
            <button style="background: transparent;border: transparent;cursor: pointer;" (click)="readUser(user.id)">{{user?.id}}</button>
            </td>
        </tr>
    </table>

</div>
<div style="text-align: center;">
    <span style="color: darkgray;">Identity:</span> <span style="color: gray;">{{user.id}}</span> <br>
    <span>Name:</span> {{user.name}} <br> 
    <span>School:</span> {{user.school}} <br> 
</div>

【问题讨论】:

  • 请发布您的代码和错误信息。
  • 没问题。
  • 我没有看到你在模板中使用 *ngIf
  • @DanielF 请检查问题中的代码。
  • ngIf 在哪里??

标签: angular async-await angular-ng-if


【解决方案1】:

我认为您必须使用 ngIf,因为您的模板会在获取数据之前加载。 因此,您的 HTML 已准备好获取数据。你可以做的,而且它更干净,是创建一个布尔变量:

isDataReady: Boolean = false;

然后在您的 html 中使用它,因为它始终为 false,直到您在订阅获取数据时在组件中更改它。

另外,在我的项目中,我使用了一个角度材质微调器,让用户知道它使用我创建的这个变量加载后端数据。

希望对你有帮助!

【讨论】:

  • 实际上,在从服务器获取数据之前加载模板是正确的。如果我不使用 *ngIf ,则会收到错误“错误类型错误:无法读取 Object.eval [as updateRenderer] 处未定义的属性 'id'”>>>>所以我试图不使用 *ngIf 并且我可以得到解决。 *POINT IS 我有这么多模板,所以我不能浪费时间到处添加 *ngIf。这就是事情。谢谢
  • 你可以用条件将所有包含 api 数据的东西包装在一个大 div 中,它只是一个 ngif
【解决方案2】:

我认为您没有以正确的方式使用*ngIf。您只需在模板中添加一个*ngIf,如下所示,您不需要为每个标签添加多个*ngIf。

<div style="text-align: center;" *ngIf="user">
    <span style="color: darkgray;">Identity:</span> <span style="color: gray;">{{user.id}}</span> <br>
    <span>Name:</span> {{user.name}} <br> 
    <span>School:</span> {{user.school}} <br> 
</div>

【讨论】:

  • 我知道 *ngIf 会显示用户信息。但这只是 HTML 的一小块,我有很多块!所以我对这个问题的观点是找到一种避免 *ngIf 的方法,我也可以在不使用 *ngIf 的情况下向用户显示信息!
  • 在需要时在模板中使用 *ngif 并没有什么害处,它的目的是仅有条件地显示和隐藏信息,它是在模板中隐藏或显示内容的最简洁方式转角
  • Shijil Narayan 是的,你是对的!但如果你能帮我找到替代方法
  • 有很多肮脏的方法可以做到这一点,比如在你的 html 上使用 css display none 并在你从后端获取用户对象时将其设置为在 typescript 中显示块,但我永远不会推荐你这样做那
【解决方案3】:

Angular 有一个生命周期系统,因此 Angular 会在从您的 API 获取数据之前尝试加载组件。所以是的,您需要在 API 响应之前处理此案例。

你有两种方法可以做到这一点:

  • 使用 *ngIf 但如果您担心这种情况,您不必在任何地方都使用 *ngIf,如果您进行多次调用,您可以正确使用 ngrx 并仅在 HTML 中使用一个 *ngIf

  • 使用默认值初始化您的数据。如果当然没有错误,Angular 将加载您的“默认”用户并将其替换为 API 接收到的用户。如果您真的想使用它,请尝试

user: user = new user();

当然,在用户构造函数中,用空字符串初始化你正在使用的所有属性。

但我认为第一种方法更好,因为您可以使用加载微调器、加载和错误消息更正确地处理错误和等待情况,...但是您需要学习 rxjs 的基础知识 :)

【讨论】:

    【解决方案4】:

    您用于存储 userResult 的代码不是承诺,而是订阅:

    async readUser(id){
         // this block is wrong, userResult is a subscription
         this.userResult = await this.http.get<user>("http://localhost:8090/user/" +id).subscribe(
           data => {
             this.user = data;
           },
           error =>{
             return console.error();
             ;
           }
         )
        console.log("Fuuhhh! Client will wait till promise is resolved.");
      }
    

    如果您想使用 Promise(但您应该在 Angular 中使用 observables),您可以使用 toPromise() 方法,如下所示:

    async readUser(id){
         try {
           this.userResult = await this.http.get<user>("http://localhost:8090/user/" +id).toPromise();
           this.user = this.userResult // if you really want an extra step here
        } catch(error) {
          console.log(error);
        }
      }
    

    关于您的问题,您应该在这种情况下使用*ngIf

    对于代码块,将其与ng-container 一起使用,如下所示:

    <ng-container *ngIf="user">
       .....
    </ng-container>
    

    【讨论】:

      【解决方案5】:

      感谢大家以不同的方式帮助我。但是,是的,我没有从答案中得到解决方案。

      最后,我自己对“避免 *ngIf”进行了一些研发,得到了解决方案,以下是简短的解决方案:

      使用 Angular “解析器”服务,我在渲染模板/视图之前获取了数据。

      【讨论】:

        猜你喜欢
        • 2023-04-11
        • 2017-02-07
        • 2018-09-08
        • 2020-04-04
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 2020-01-04
        相关资源
        最近更新 更多