我正在尝试创建一些内部带有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);
}
}
}
答案 0 :(得分:2)
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
。另一种情况是scope
更改时。让我们以以下代码为例:
function something(){
this; //A
this.service.getData
.subscribe( res => {
this; //B
});
}
引用注释this
的 A
是组件。如果在该点上设置断点,则会看到组件的方法和属性。
this
(注释B)的 .subscribe
不再是组件,而是订阅。那是范围的变化,并且可能引起一些刷新问题。
在javascript中,这种情况更常见,例如IE:在回调中使用this
的范围是不同的。但是angular是聪明的,即使在订阅中也知道,如果您执行this.componentMethod()
,则试图调用属于该组件的函数。
那为什么要使用cdr?
正如我所说,在某些情况下Angular不唤醒其渲染器。由于每种情况都不尽相同,因此不可能对此定义绝对的答案。这就是为什么我的范围示例发生变化的原因。 cdr.detectChanges()
的作用是允许该方法通知Angular的渲染以强制其component.html的渲染。这样,无论您使用哪个strategy
(即使它是.onPush
),该组件都将重新呈现。
但是要小心。您必须先考虑自己在做什么,然后再执行此操作。例如,重新渲染html引发ngOnChanges
事件。这样您就可以进入一个无限循环。
有关cdr的更多信息:https://angular.io/api/core/ChangeDetectorRef
希望这消除了一些疑问。
答案 1 :(得分:0)
如果您只是将MenuItem item = _menu.findItem(R.id.menu_item_id);
item.setIcon(ContextCompat.getDrawable(getViewContext(), R.drawable.ic_search_24dp));
或数据推入数组,则object
不会将其检测为已更改属性(这很不好)。因为您没有完全重新分配它。
您可以做的是:
angular
(虽然不是一个好的解决方案)。答案 2 :(得分:0)
使用具有唯一的return语句的自定义trackby函数(例如,ID应该是唯一的,或者您可以在更改的属性上进行跟踪)
*ngFor="let data of mySaleModelArray2; trackBy: customTB"
customTB(item, index) {
return `${item.id}-${index}`;
}