显示带有加载和错误情况的数据

时间:2018-04-20 08:50:48

标签: angular typescript

在Angular中,考虑到加载状态和错误情况,在视图中显示数据的有效方法是什么?

假设我们从后端获取了一组文档,并希望使用Angular在我们的视图中显示这些文档。我想要考虑3个州。对于每个状态,我想向用户显示一条消息:

  1. 加载您的数据......
  2. 尝试检索数据时出错!
  3. 数据检索成功!
  4. 目前,我正在做以下事情。我面临的问题是在加载阶段会短暂显示“加载”和“错误”消息。

    我想知道其他人如何解决这个常见的用例?是否可以通过为myDocs变量分配不同的值来实现,或者我是否必须引入另一个变量?

    TS

    export class MyDocsComponent implements OnInit {
    
        myDocs: IMyDoc | null;
    
        ngOnInit() {
    
            // get myDocs
            this.myDocsService.getMyDocs()
    
            // if success
            .then( myDocs => { this.myDocs = myDocs; })
    
            // if error: could not get myDocs from service
            .catch( error => {
                // what should go in here
                // and how should this be checked in the view
                // to display an error message to the user
                // if the data could not be retrieved
                // while also being able to display a loading message beforehand
    
                // currently, I am doing:
                this.myDocs = null;
                // however, this leads to the error message 
                // incorrectly being displayed 
                // while loading the data
            });
        }
    }
    

    HTML

    <!-- loading -->
    <div class="loading" *ngIf="!myDocs">
        Loading your data...
    </div>
    
    <!-- error -->
    <div class="error" *ngIf="myDocs==null">
        Error trying to retrieve your data!                         
    </div>
    
    <!-- success -->
    <div class="success" *ngIf="myDocs">
        Data retrieved successfully!
        <div class="list" *ngFor="let d of myDocs">{{ d.title }}</div>
    </div>
    

2 个答案:

答案 0 :(得分:2)

尝试这样的事情

<强> component.ts

export class MyDocsComponent implements OnInit {

  myDocs: IMyDoc | null;

  state: 'loading' | 'loaded' | 'error' = 'loading';

  isLoading() {
    return this.state === 'loading';
  }

  isError() {
    return this.state === 'error';
  }

  isLoaded() {
    return this.state === 'loaded';
  }

  ngOnInit() {
    this.myDocsService.getMyDocs()
      .then(myDocs => {
        this.myDocs = myDocs;
        this.state = 'loaded';
      })
      .catch(error => {
        console.log(error);
        this.state = 'error';
      });
  }
}

<强> component.html

<div *ngIf="isLoading"  class="loading">
  Loading your data...
</div>

<div *ngIf="isError" class="error">
  Error trying to retrieve your data!
</div>

<div *ngIf="isSuccess" class="success" >
  Data retrieved successfully!
  <div class="list" *ngFor="let d of myDocs"> {{ d.title }}
  </div>
</div>

答案 1 :(得分:0)

这是处理同一问题的另一种方法。我正按照OP的要求将其移至另一个答案。不要投票。

这使用了一些更高级的角度API,比如

  • async pipe
  • <ng-container>
  • as表达式中的
  • *ngIf个关键字
  • else loading<ng-template #loading>
  • 相结合

<强> component.ts

  export class MyDocsComponent implements OnInit {
    myDocs$: Promise < IMyDoc | string > ;

    ngOnInit() {
      this.myDocs$ = this.myDocsService.getMyDocs()
        .catch(error => {
          console.log(error);
          return 'there was an error';
        });
    }

    isError(resp: IMyDoc | string) {
      return typeof resp === 'string';
    }


    isSuccess(resp: IMyDoc | string) {
      return typeof resp !== 'string';
    }
  }

<强> component.html

<div *ngIf="myDocs$ | async as myDocs; else loading">
  <ng-container *ngIf="isSuccess(myDocs)" >
    <div class="success"
       Data retrieved successfully!
       <div class="list" *ngFor="let d of myDocs"> {{ d.title }}       
       </div>
    </div>
  </ng-container>

  <ng-container *ngIf="isError(myDocs)">
    <div *ngIf="isError" class="error">
      Error trying to retrieve your data!
    </div>
  </ng-container>
</div>

<ng-template #loading>
  <div *ngIf="isLoading" class="loading">
    Loading your data...
  </div>
</ng-template>