我正在尝试根据信号的值过滤数组,我认为计算信号是实现此目的的最佳选择。我的目标是仅显示与(通过自定义过滤功能)通过切换按钮在另一个组件中设置的相应反馈过滤器相匹配的结果。
父组件ts文件
export interface Data {
name: string;
total_fb: number;
last30: number;
trend: string;
}
...
dataArray = [
{name: 'Prod XY', total_fb: 4.5, last30: 3.6, trend: 'up'},
{name: 'Prod lorem ipsum Z', total_fb: 4.2, last30: 3.3, trend: 'up'},
{name: 'Prod VBG', total_fb: 3.3, last30: 3.7, trend: 'up'},
{name: 'Prod XYZ', total_fb: 3.7, last30: 2.9, trend: 'down'},
...
];
filtersProd = signal({source: '1', feedback: 'all'});
filteredProdData = computed(() => {
const rating = this.filtersProd().feedback;
return this.dataArray.filter((el) => this.filterByFeedBackRating(el, rating));
});
filterByFeedBackRating = (data: Data, rating_value: string) => {
if (rating_value === 'all') {
return true;
} else if (rating_value === '4+' && data.total_fb >= 4) {
return true;
} else if (rating_value === '3' && data.total_fb >= 3 && data.total_fb < 4) {
return true;
} else if (rating_value === '1/2' && data.total_fb < 3) {
return true;
}
return false;
}
父组件模板
<div class="pre-content">
<pre>source: {{filtersProd().source}} rating: {{filtersProd().feedback}}</pre>
<app-filter-source-feedback [(filters)]="filtersProd"></app-filter-source-feedback>
</div>
<div class="content flex">
<app-table-performance [data]="filteredProdData()"></app-table-performance>
</div>
FilterSourceFeedback组件ts文件
filters = model.required<{feedback: string|number, source: string}>();
FilterSourceFeedback 组件模板
<div class="toggle">
<label>Feedback</label>
<mat-button-toggle-group [(value)]="filters().feedback" hideSingleSelectionIndicator="true" name="feedback" aria-label="feedback rating">
<mat-button-toggle value="all">all</mat-button-toggle>
<mat-button-toggle value="4+">4+</mat-button-toggle>
<mat-button-toggle value="3">3</mat-button-toggle>
<mat-button-toggle value="1/2">1/2</mat-button-toggle>
</mat-button-toggle-group>
</div>
TablePerformance组件ts文件
data = input<Data[]>([]);
dataSource = computed(() => new MatTableDataSource(this.data()));
columnsToDisplay = ['name', 'total_fb', 'last30', 'trend'];
TablePerformance 组件模板
<table mat-table [dataSource]="dataSource()">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let tourStat"> {{tourStat.name}} </td>
</ng-container>
<ng-container matColumnDef="total_fb">
<th mat-header-cell *matHeaderCellDef> Total </th>
<td mat-cell *matCellDef="let tourStat"> {{tourStat.total_fb}} </td>
</ng-container>
...
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: columnsToDisplay"></tr>
</table>
当我更改反馈切换按钮组的值时,父组件中的
filtersProd
信号与子组件中的模型信号 filters
完美同步。问题是计算信号 filteredProdData
返回的数组仅使用初始值进行过滤(如果我更改初始值,我会在表中获得正确的过滤结果),后续更新不会过滤初始数组,就好像计算信号不会“监听”其依赖项的更新。
自从我上次使用 Angular 的版本以来,信号功能还没有发布,但我不明白我哪里出了问题或者我错过了什么。
您的代码不起作用的原因是因为默认情况下,Angular 信号使用引用相等来跟踪值是否已更改。您将对象存储在信号中,这意味着只要对象的引用相同,该值就被视为未更改。如果您只是在更新中更新属性,就像使用
[(value)]="filters().feedback"
进行绑定时所做的那样,则引用保持不变。 Angular 认为该值没有改变,因此不会发生重新计算。
要以干净的方式解决问题,您应该为过滤器的
source
和 feedback
提供单独的信号,而不是将它们都存储在一个对象中。您可以直接在信号上使用双向绑定(无需读取值),如下所示:
<mat-button-toggle-group [(value)]="filtersFeedback"> ...
按照我的建议,假设组件中有
filtersFeedback
信号。