【问题标题】:My view does not update when i change my array in *ngFor当我在 *ngFor 中更改我的数组时,我的视图没有更新
【发布时间】:2020-05-21 21:58:53
【问题描述】:

我正在尝试在内部创建一些带有 mat-table 的扩展面板,我的问题是我必须在我的视图改变之前调整我的窗口大小。我的数据加载正常,但不知何故我的视图没有更新。我的扩展面板应该在哪里,我的视图都是空白的。直到我单击一个按钮或调整我的窗口大小。什么会导致这种情况?

在我的 ngOnInit() 中我调用

this.getSale1(); 

.HTML:

<mat-accordion>
    <mat-expansion-panel *ngFor="let data of mySaleModelArray2 ">
        <mat-expansion-panel-header>
            <mat-panel-title>
                <h6 class="salepanelheadtext">Bar:</h6>{{data.name}}
            </mat-panel-title>
        <mat-panel-description>
            <h6 class="salepanelheadtext2">Total:</h6> {{data.total_sales}}
        </mat-panel-description>
        </mat-expansion-panel-header>
            <div class="example-container mat-elevation-z8">                                
                <mat-table #table [dataSource]="data.sales"  >
                <!-- PLU Column -->                                 
                <ng-container matColumnDef="pluNo">
                    <mat-header-cell *matHeaderCellDef >
                        #
                    </mat-header-cell>
                    <mat-cell *matCellDef="let salesdata"> 
                        {{salesdata.beerline}} 
                    </mat-cell>
                </ng-container>
                <!-- Name Column -->
                <ng-container matColumnDef="name">
                    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
                    <mat-cell *matCellDef="let salesdata"> 
                         {{salesdata.pluName}} 
                    </mat-cell>
                </ng-container>
                <!-- Sold_Count Column -->
                <ng-container matColumnDef="sold_count">
                    <mat-header-cell *matHeaderCellDef> 
                        QTY 
                    </mat-header-cell>
                    <mat-cell *matCellDef="let salesdata"> 
                        {{salesdata.sold_count}} 
                    </mat-cell>
                </ng-container>
                <!-- PLU Price Column -->
                <ng-container matColumnDef="pluPrice">
                    <mat-header-cell *matHeaderCellDef> Price </mat-header-cell>
                    <mat-cell *matCellDef="let salesdata"> 
                        {{salesdata.pluPrice}} 
                    </mat-cell>
                </ng-container>
                <!---->
                <ng-container matColumnDef="total_amount">
                    <mat-header-cell *matHeaderCellDef> 
                        Total 
                    </mat-header-cell>
                    <mat-cell *matCellDef="let salesdata"> 
                        {{salesdata.pluPrice * salesdata.sold_count}} 
                    </mat-cell>
                </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns2"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns2;"></mat-row>
            </mat-table>
        </div>
    </mat-expansion-panel>
</mat-accordion>

.TS:

//Get data from Sale1List
getSale1() {        
    this.customersService.getSale1()
    .subscribe(
        dataList => {                    
                this.updateDataTable(dataList);
         }               
     )       
 }


updateDataTable(dataList) { 
for(var i = 0;i < dataList.length; i++){
    var saleData = <SaleDataModel>dataList[i];

   var mySaleModelTest = this.mySaleModelArray2.find(x => x.name == dataList[i].name);
   if(mySaleModelTest == null){
       //first time creating the object with the bar name
       var tempArray = Array();
       tempArray.push(saleData);

       this.mySaleModelArray2.push(new Sale1Model(dataList[i].name,dataList[i].pluPrice * dataList[i].sold_count,tempArray));

   }else{                           
       //changing the object with the bar name because it already exist
       mySaleModelTest.total_sales = mySaleModelTest.total_sales + dataList[i].pluPrice * dataList[i].sold_count;
       mySaleModelTest.sales.push(saleData);
   }                    
   }    
}

【问题讨论】:

  • 您是否将ChangeDetectionStrategy 设置为OnPush
  • 您可以尝试使用 ChangeDetectorRef -> detectChanges
  • 我将它从 .OnPush 更改为 .Default。对我来说没有任何变化。
  • @JacopoSciampi this.updateDataTable(dataList); this.changeDetectorRef.detectChanges();这会成功的。仍然想知道为什么。但至少是迄今为止最糟糕的观点
  • @SonnyHansen 我会为此发布一个答案。请让我几分钟。

标签: angular


【解决方案1】:

ChangeDetectorRef 可以解决问题。

在构造函数中注入他。

constructor(
  ... 
  private cdr: ChangeDetectorRef,
  ...
) { }

像这样编辑 getSale1 以使用 cdr:

getSale1() {        
    this.customersService.getSale1()
    .subscribe(
        dataList => {                    
                this.updateDataTable(dataList);
                this.cdr.detectChanges();
         }               
     )       
 }

但为什么我必须使用 ChangeDetectorRef?

默认情况下,Angular 使用ChangeDetectionStrategy.default,它使用其逻辑“唤醒”渲染组件。更多规格在这里:https://angular.io/api/core/ChangeDetectionStrategy

在某些情况下,这还不够。一个案例可能是一个非常大的嵌套*ngFor

那么为什么要使用 cdr?

正如我所说,在某些情况下 Angular 不会唤醒其渲染器。由于每种情况都不相同,因此很难定义一个绝对的答案。 cdr.detectChanges() 所做的是允许该方法通知 Angular 的已渲染以强制其 component.html 的渲染。这样,无论你使用的是哪个strategy(即使是.onPush),组件都会被重新渲染。

但是要小心。在执行此操作之前,您必须考虑自己在做什么。例如,重新渲染 html 会触发 ngOnChanges 事件。所以你可以进入一个无限循环。

更多关于 cdr 的信息:https://angular.io/api/core/ChangeDetectorRef

希望这能消除一些疑虑。

【讨论】:

  • 不客气。在过去的日子里,我也挣扎了几个月来理解这一点。非常感谢我的回答对您有所帮助!
  • @JacopoSciampi 感谢您的时间和精力!感谢您的回答
  • 我知道这与问题无关,我真的只是需要释放一些空气。我已经为此苦苦挣扎了几个小时。对我来说,这就是 Angular 如此不直观的原因,我更喜欢使用 React。我想是时候换工作了......很好的答案!
  • 我不知道您的问题是什么,但是始终强制 Angular 重新渲染的一个很酷的技巧是为绑定的对象分配一个新对象。一个简单的this.myBindedVariable = JSON.parse(JSON.stringify(myVar)); 就可以了!
【解决方案2】:

使用带有唯一返回语句的自定义 trackby 函数(例如,ID 应该是唯一的,或者您可以跟踪您更改的属性)

*ngFor="let data of mySaleModelArray2; trackBy: customTB"
customTB(item, index) {
  return `${item.id}-${index}`;
}

【讨论】:

  • 这应该是公认的答案。它立即解决了我的问题,而且非常简单。
  • 请注意trackBy函数接口好像更新为:customTB(index, item) 来源:angular.io/api/core/TrackByFunction
【解决方案3】:

如果您只是将object 或数据推送到数组中,angular 不会将其检测为已更改的属性(这很糟糕)。因为你没有完全重新分配给它。

你可以做的是:

  1. 您可以手动执行更改检测
  2. 使用临时数组重新分配整个数组 mySaleModelArray2(虽然不是一个好的解决方案)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2019-12-18
    相关资源
    最近更新 更多