(TL;DR: Summary of questions is found below)
I have a large data set which I want to filter using multiple criteria. It's all working nicely however I had to do some nasty things which I want to get rid of.
I'm using the angular2-datatable package, but I guess the problem rather lies somewhere in my lack of understanding of angular. So one of the nastier things was that I had to create one pipe per filter criteria.
<table class="table table-striped" [mfData]="(((data | wstateFilter : filterQuery.wstate ) | dataSubjectFilter : filterQuery.subject) | dataResponsibilityFilter : filterQuery.personResponsible) | issuedByFilter : filterQuery.issuedBy" #mf="mfDataTable">
This may not look too nasty now, but this might later explode into at least 20-50 pipes for just 4 Datasets.
I want to define a FilterQuery Object that contains all filter criteria, and one corresponding pipe that takes these objects as queries.
<table [mfData]="((data | dataSetFilter : filterQuery" #mf="mfDataTable">
The query object now looks like:
export class TaskQuery {
public subject: string;
public wstate: TaskWorkstate;
public personResponsible: string;
public issuedBy?: string;
}
I have defined the Pipe like this:
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;
}
}
So far so good the pipe is working as it is supposed to. For hard-coded TaskQuery objects the pipe does what I want. The problem starts when I want to use databinding to the variables of the TaskQuery object.
For example:
<input class="form-control" [(ngModel)]="filterQuery.personResponsible" />
When this is done the change detection isn't triggered and the data is not put through the pipe. I guess because Angular probably just looks at the reference to the object filterQuery
, which obviously remains the same.
This simple workaround doesn't work either:
<input class="form-control" [ngModel]="filterQuery.subject" (ngModelChange)="temp=filterQuery; temp.setSubject($event); filterQuery=temp" />
...because Objects are passed by reference :-(.
Furthermore angular doesn't let me execute let
or new
statements in templates. Therefore I cannot create a new reference so far.
So questions:
Is it possible to mark an object somehow as changed? (this is what I would actually want)
How can I create a new object reference in the template file? (Like e.g.
<input class="form-control" [ngModel]="filterQuery.subject" (ngModelChange)="temp=new FilterQuery().copy(filterQuery); temp.setSubject($event); filterQuery=temp">
)