Angular-正确获取响应并填充支持数组,但是Angular html组件仅看到空数组

时间:2019-06-20 19:52:06

标签: angular asynchronous

我正在尝试根据从宁静的服务(当前返回日期列表)收到的响应来填充日历。

我正在从组件的ngInit()方法中调用restful服务方法。

 ngOnInit() {
    this.refreshCalendar(); 

    for (var calendarEntryShortvar of this.calendarEntriesShort) {
      console.log("cal entry short from ngInit: " + calendarEntryShortvar.start);
    }

  }

由于内容长度不确定,上述循环打印内容失败。

这是this.refreshCalendar();的代码。

 refreshCalendar(){
    this.calendarService.retrieveAllCalendarEntriesShort('test')
    .subscribe (
      response => {
        console.log("printing response")
        console.log(response)
        this.calendarEntriesShort = response; 

        for (var calendarEntryShortvar of this.calendarEntriesShort) {
          console.log("cal entry short: " + calendarEntryShortvar.start);
          this.calendarEntry =  new CalendarEntry(calendarEntryShortvar.start, calendarEntryShortvar.start, 
          'title event 1', this.colors.redx, this.actions);
          console.log("pushing calendar entry")
          this.events.push(this.calendarEntry);     
        }

       }
    )

  }

上面的代码成功打印了数组的内容,这意味着它在收到服务的响应后正在执行。

以下是服务呼叫的代码:

retrieveAllCalendarEntriesShort(用户名){

console.log("retrieveAllCalendarEntries"); 

return this.http.get<CalendarEntryShort[]>(`${CALENDER_API_URL}/users/${username}/calendarentries`);

}

不用说,在填充日历日期数组之前,将呈现日历的HTML。这是HTML组件:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
<angular-calendar-year-view  [events]="events"  [viewDate]="viewDate" [customTemplate]="Customtemplate" ></angular-calendar-year-view>
<ng-template #Customtemplate>
        My custom templatex
</ng-template>
<angular-calendar-year-view  
       [themecolor]="themecolor" 
       [events]="events"  
       [viewDate]="viewDate"  
       [nothingToshowText]="nothingToshowText"
       (eventClicked)="eventClicked($event)" 
       (actionClicked)="actionClicked($event)" >
</angular-calendar-year-view>

以某种方式,我需要让Angular暂停直到收到响应。这仅仅是使其成为同步呼叫的问题吗?我不确定为什么这行不通。

2 个答案:

答案 0 :(得分:1)

在Angular中有几种处理异步调用的方法。我的第一个选择通常是尽可能使用异步管道(因此无需担心取消订阅)。这样的事情应该适合您:

更新您的api服务调用,以在可观察对象上进行映射,并为其添加变量:

calendarResults$: Observable<CalendarEntry[]>;

refreshCalendar() {
  this.calendarResults$ = this.calendarService.retrieveAllCalendarEntriesShort('test')
      .pipe(map((response: any[]) => {
        return response.map(calendarEntryShortvar => {
          return new CalendarEntry(calendarEntryShortvar.start, calendarEntryShortvar.start, 'title event 1', this.colors.redx, this.actions)
        });
      }));
}

然后,您可以在* ngIf模板中使用异步管道(可以显示一些加载动画):

<ng-container *ngIf="calendarResults$ | async as calendarResults; else loading"
    <angular-calendar-year-view  [events]="calendarResults"  [viewDate]="viewDate" [customTemplate]="Customtemplate" ></angular-calendar-year-view>
    // your other code dependent on this async data
</ng-container>
<ng-template #loading>
    Loading...
</ng-template

答案 1 :(得分:0)

您必须等待响应后再进行处理。另外,您可以等待它,然后再将处理它的html部分添加到视图中。

将api调用放入服务中,这是最好的做法:

为您服务

// service.ts
refreshCalendar() {
    return this.calendarService.retrieveAllCalendarEntriesShort('test');
}

在您的组件中:

events: any = [];

constructor(private service: Service) {}

ngOnInit() {
    this.service.refreshCalendar()
    .subscribe(response => {
        this.calendarEntriesShort = response;
        for (var calendarEntryShortvar of this.calendarEntriesShort) {
          console.log("cal entry short from ngInit: " + calendarEntryShortvar.start);
          for (var calendarEntryShortvar of this.calendarEntriesShort) {
              this.calendarEntry =  new CalendarEntry(calendarEntryShortvar.start, 
             calendarEntryShortvar.start, 
             'title event 1', this.colors.redx, this.actions);
             this.events.push(this.calendarEntry);     
           }
        }
    });
}

您认为

<div *ngIf="events.length > 0">
    <angular-calendar-year-view  [events]="events"  [viewDate]="viewDate" 
    [customTemplate]="Customtemplate" >
    </angular-calendar-year-view>
    <ng-template #Customtemplate>
        My custom templatex
    </ng-template>
    <angular-calendar-year-view  
        [themecolor]="themecolor" 
        [events]="events"  
        [viewDate]="viewDate"  
        [nothingToshowText]="nothingToshowText"
        (eventClicked)="eventClicked($event)" 
        (actionClicked)="actionClicked($event)" >
    </angular-calendar-year-view>
</div>