仅* ngIf指令的第一个匹配项返回ExpressionChangedAfterItHaHasBeenCheckedError

时间:2019-12-11 14:26:40

标签: angular ngfor angular-ng-if

我在ngfor中有一个嵌套的ngif:

<ion-content>
    <ng-container *ngFor="let item of (results | async)">
      <ng-container *ngFor="let elements of item.bc; first as isFirst; index as i">
        <ng-container *ngIf="elements.Event.StartTime >= '2019-12-11T15:00:00' ?func():false">
          <ion-item>{{elements.Event.StartTime | date:'shortTime'}}</ion-item>
        </ng-container>
      </ng-container>
    </ng-container>
</ion-content>

我从这里看到了带有功能的分辨率:enter image description here

export class Tab4Page implements OnInit {

  results: Observable<any>;
  isFirstMatch = false;

  constructor(private channel: Service) {
  }

func() {
    if (this.isFirstMatch === false) {
      this.isFirstMatch = true;
      return true;
    } else {
      return false;
    }
  }

  ngOnInit() {

    this.results = this.channel.searchData();
  }

}

但这对我不起作用。我收到此错误:

ExpressionChangedAfterItHaHasBeenCheckedError:检查表达式后,表达式已更改。先前的值:'ngIf:true'。当前值:'ngIf:false'。

是否有更好的方法只输出第一个比赛?否则,请告诉我如何解决ExpressionChanged错误。

2 个答案:

答案 0 :(得分:1)

您可以检查ts中首次出现的情况:

html

<ion-content>
    <ng-container *ngFor="let item of (results | async)">
      <ng-container *ngIf="findFirstElement(item.bc) as element">
          <ion-item>{{element.Event.StartTime | date:'shortTime'}}</ion-item>
        </ng-container>
    </ng-container>
</ion-content>

ts

  findFirstElement(item : any[]){
    if (!this.isFirstMatch && item.some(el => el.Event.StartTime >= '2019-12-11T15:00:00')){
      this.isFirstMatch = true ;
      return item.find(el => el.Event.StartTime >= '2019-12-11T15:00:00') ;
    }

    return null ;
  }

更新

我认为不再需要isFirstMatch标志,因为您希望为每个迭代(项目)呈现第一个出现的对象:

  findFirstElement(item : any[]){
      return item.find(el => el.Event.StartTime >= '2019-12-11T15:00:00') ;
  }

答案 1 :(得分:1)

只需在代码中完成

this.firstMatches$ = this.results.pipe(
  map(results => // rx map operator
    results.map(item => // array map operator to transform
      item.bc.find(el => // into first found match
        el.Event.StartTime >= '2019-12-11T15:00:00')))
);


<ion-content>
  <ng-container *ngFor="let item of (firstMatches$ | async)">
    <ion-item>{{item.Event.StartTime | date:'shortTime'}}</ion-item>
  </ng-container>
</ion-content>

OR:

this.firstMatch$ = this.results.pipe(
  map(results => // rx map operator
    results.find(item => // find first item
      !!item.bc.find(el => // that contains a match
        el.Event.StartTime >= '2019-12-11T15:00:00'))),
  map(item => item.bc.find(el => el.Event.StartTime >= '2019-12-11T15:00:00')) // map into that element
);


<ion-content>
  <ng-container *ngIf="firstMatch$ | async as item">
    <ion-item>{{item.Event.StartTime | date:'shortTime'}}</ion-item>
  </ng-container>
</ion-content>

代码比模板强大得多,请使用它。

模板很难阅读和理解。我不清楚您是要显示一个ion-item(对于所有项目中的第一个匹配元素)还是显示多个(对于每个项目中的第一个匹配元素)。显示了两个答案。