如何在将用户定义的“查询” – 对象传递给管道而不是字符串(Angular 2)时保持更改检测活动?

(TL; DR:问题摘要见下文)

嗨,大家好.

我有一个大型数据集,我想使用多个条件进行过滤.这一切都很好,但我不得不做一些我想摆脱的讨厌的事情.

我正在使用angular2-datatable包,但我认为问题在于我对角度缺乏了解.因此,一个更糟糕的事情是我必须为每个过滤条件创建一个管道.

<table class="table table-striped" [mfData]="(((data | wstateFilter : filterQuery.wstate ) | dataSubjectFilter : filterQuery.subject) | dataResponsibilityFilter : filterQuery.personResponsible) | issuedByFilter : filterQuery.issuedBy" #mf="mfDataTable">

现在看起来可能不太讨厌,但是这可能会在4个数据集中爆炸至少20-50个管道.

我想定义一个包含所有过滤条件的FilterQuery对象,以及一个将这些对象作为查询的相应管道.

<table [mfData]="((data | dataSetFilter : filterQuery" #mf="mfDataTable">

查询对象现在看起来像:

export class TaskQuery {
    public subject: string;
    public wstate: TaskWorkstate;
    public personResponsible: string;
    public issuedBy?: string;
}

我已经像这样定义了Pipe:

import * as _ from "lodash"
import { Pipe, PipeTransform } from "@angular/core";
import { Task, TaskQuery } from './task.import'

@Pipe({
     name: "dataSetFilter"
     })
export class QueryPipe implements PipeTransform {
    transform(array: Task[], query: TaskQuery): any {
        array = _.filter(array, function (o) {
            if (!(o.subject.indexOf(query['subject']) > -1)) return false;
            if (o['personResponsible'].indexOf(query['personResponsible']) < 0) return false;
            if (o.hasOwnProperty('issuedBy')) {
                if (o['issuedBy'].indexOf(query['issuedBy']) < 0) return false;
            }
            return true;
        });
        return array;
    }
}

到目前为止管道是如此的好,正如它应该的那样.对于硬编码的TaskQuery对象,管道可以满足我的需求.当我想对数据绑定使用TaskQuery对象的变量时,问题就出现了.

例如:

 <input class="form-control" [(ngModel)]="filterQuery.personResponsible" />

完成此操作后,不会触发更改检测,并且数据不会通过管道.我想因为Angular可能只是查看对象filterQuery的引用,显然它仍然是相同的.

这个简单的解决方法也不起作用……

< input class =“form-control”[ngModel] =“filterQuery.subject”(ngModelChange)=“temp = filterQuery; temp.setSubject($event); filterQuery = temp”/>

…因为对象通过引用传递:-(.

此外,angular不允许我在模板中执行let或new语句.因此到目前为止我无法创建新的引用.

所以问题:

>是否可以将某个对象标记为已更改? (这就是我真正想要的)
>如何在模板文件中创建新的对象引用? (例如< input class =“form-control”[ngModel] =“filterQuery.subject”(ngModelChange)=“temp = new FilterQuery().copy(filterQuery); temp.setSubject($event); filterQuery = temp “>
)

最佳答案 我通过在xyz.component.ts中定义一个方法newQuery()来实现它,该方法可以从模板调用(ngModelChange)=“filterQuery.set(‘subject’,$event); newQuery()”

newQuery()函数生成一个新引用并覆盖旧引用

public newQuery(): void {
    this.filterQuery = Object.assign(new TaskQuery(), filterQuery);
}

我并不完全满意,因为它仍然感觉像是一个不那么肮脏的工作.然而,它消除了迄今为止的大多数缺点.

点赞