【问题标题】:How can I access the object property inside subscribe to render the HTML?如何访问订阅内的对象属性以呈现 HTML?
【发布时间】:2020-02-17 22:15:59
【问题描述】:

我需要使用我在.subscribe 中获得的属性来更新 HTML。我知道 .subscribe 是异步的,因此在解析之前该值是未定义的,但我怎样才能让它等到它有值?目前我只得到 undefined 的对象属性。

这是我调用 API 来获取数据的服务方法:


fetchCustomers(name: string) Observable<Customer[]> {

    return this.http.get<Customer>('MY URL')

}

以及我订阅它的组件:

   customer: any;
   name: string;

  ngOnInit() {
    //this.name = /*code to retrieve the name*/
    this.renderCustomer(this.name)
  }

  renderCustomer(name) {
      this.testService.fetchCustomer(name).subscribe(data => {
      this.customer = data
  })
}

但是当我调用 this.customer 方法时仍然未定义。我需要 data 的属性来呈现我的 HTML 文件,如下所示:

 <tr> {{ customer.companyName }} </tr>
 <tr> {{ customer.fullName }} </tr>
 <tr> {{ customer.Email }} </tr>

我怎样才能让这条线this.customer = data 等到Observable 得到解决?我也尝试过this.customer = JSON.parse(JSON.stringify(data)),正如另一个帖子中所建议的那样,但它不起作用。

【问题讨论】:

  • 那一行已经等到可观察对象被解析;这就是传递回调的全部意义所在。这是没有的模板的第一个渲染。要么使用安全导航,要么使用 ngIf 有条件地渲染它,要么向模板公开一个 observable 并使用 AsyncPipe。
  • 感谢各位的回答。我目前无法访问代码。一旦我回到它,我会尝试它们
  • 那你为什么现在问这个问题?
  • 因为我在工作中做不到
  • @Peyman Kheiri - Salam Peyman ,Customer 是接口还是类?

标签: angular typescript observable


【解决方案1】:

您的代码看起来不错!可以试试用安全导航算子吗,

<tr> {{ customer?.companyName }} </tr>
<tr> {{ customer?.fullName }} </tr>
<tr> {{ customer?.Email }} </tr>

【讨论】:

  • 谢谢。这行得通。感谢所有的答案家伙!他们对我都有很大的帮助。
【解决方案2】:

您可以在 HTML 中使用安全导航运算符:

 <tr> {{ customer?.companyName }} </tr>
 <tr> {{ customer?.fullName }} </tr>
 <tr> {{ customer?.Email }} </tr>

您还可以在数据到来之前显示加载程序。比如:

<ng-container ngIf="!customer"> 
  <spinner></spinner>
</ng-container>
<ng-container ngIf="customer"> 
   ...
   <tr> {{ customer.companyName }} </tr>
   <tr> {{ customer.fullName }} </tr>
   <tr> {{ customer.Email }} </tr>
   ...
</ng-container>

【讨论】:

    【解决方案3】:

    你可以按照@Sajeetharan 的建议去做,或者将你的tr 封装到if 中:

    <ng-container *ngIf="customer">
     <tr> {{ customer.companyName }} </tr>
     <tr> {{ customer.fullName }} </tr>
     <tr> {{ customer.Email }} </tr>
    </ng-container>
    

    这样它只会在customer 有一些值时显示

    【讨论】:

      【解决方案4】:

      如果你的问题只出在 HTML 本身,你可以添加一个问号来检查是否先定义了对象:

       <tr> {{ customer?.companyName }} </tr>
      

      或者你可以简单地使用

      *ngIf="customer"
       ```` on the parent div.
      

      如果你想在组件中做其他事情,你可以打开回调来做更多事情。

      your_component.ts

      renderCustomer(name) {
            this.testService.fetchCustomer(name).subscribe(data => {
            this.customer = data;
            foo(data);
        })
      

      【讨论】:

        【解决方案5】:

        您也可以使用async 管道

        组件

         customer$: Observable<any>;
         name: string;
        
         ngOnInit() {
           this.renderCustomer(this.name)
         }
        
         renderCustomer(name) {
           this.customer = this.testService.fetchCustomer(name)
         })
        

        模板

        <tr> {{ customer.companyName | async }} </tr>
        <tr> {{ customer.fullName | async  }} </tr>
        <tr> {{ customer.Email | async  }} </tr>
        

        【讨论】:

        • 我不会这样做。 1)我不认为这有效 2)如果有效,您将对您的服务器进行多次异步调用。
        • 您显然误解了它的工作原理。 1)如果你想要更简洁的代码,你应该这样做。 2)它不会进行额外的调用。请查看这个不错的教程。 codecraft.tv/courses/angular/pipes/async-pipe/#_summary
        • 我很确定这条线不会工作{{ customer.companyName | async }}
        【解决方案6】:

        如果客户模型是一个接口,您可以为每个属性设置默认值 null,如下所示

        public customer:Customer={ companyName: null, fullName: null, Email:null } 
        

        然后在你的 html 中:

        <tr> {{ customer.companyName }} </tr>
        <tr> {{ customer.fullName }} </tr>
        <tr> {{ customer.Email }} </tr>
        

        另一种方法是使用? 运算符,如下所示:

        <tr> {{ customer?.companyName }} </tr>
        <tr> {{ customer?.fullName }} </tr>
        <tr> {{ customer?.Email }} </tr>
        

        【讨论】:

          【解决方案7】:

          如果客户和姓名都来自订阅,您可以使用 rxjs flatMap https://rxjs-dev.firebaseapp.com/api/operators/flatMap 将它们链接在一起

          customer: any;
          name: string;
          
          ngOnInit() {
            this.renderCustomer();
          }
          
          renderCustomer() {
             this.testService.fetchName(/*variable to retrieve the name*/)
              .pipe(
                flatMap((name: string) => {
                  this.name = name;
                  return this.testService.fetchCustomer(name);
                })
              ).subscribe(data => {
                 this.customer = data;
              });
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-13
            • 1970-01-01
            • 2020-01-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多