Angular语言 - 如何解密PipeTransform?



我使用*ngFor来显示集合,我也有一个input将用作过滤标准(此inputformControl)。现在我已经添加了一个PipeTransform来过滤基于input的集合。一切都如我所料,但我不知道该如何反驳。我希望我的filterPipeinput内的最后一次击键后被调用0.5s,但目前它在input内的任何更改后立即被调用。

HTML:


<div class="test-ctr">
<div class="form-ctr">
<form class="example-form" [formGroup]="filterForm">>
<input formControlName="nick" placeholder="ex. hdw"> 
</form>
</div>
<div class="app-cards-ctr">
<div class="app-card-ctr" *ngFor="let nick of nicks | filterPipe: filterForm.get('nick')?.value">
<app-card [nick]="nick"></app-card>
</div>
</div>
</div>

Component.ts:


import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';

@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {
nicks: string[] = ['Siema', 'Elo', 'Tu', 'Hdw3DCtV', 'and', 'Gównow', 'Zdzisiu11', 'Zdzisiu1','Zdzisiu2','Zdzisiu3','Zdzisiu4','Zdzisiu5'];

constructor(private formBuilder: FormBuilder) {}

filterForm = this.formBuilder.group({
nick: ['']
})

ngOnInit(): void {}
}

Pipe.ts:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'filterPipe', pure: true })
export class FilterPipe implements PipeTransform {
transform(value: string[], arg: string): string[] {
console.log(arg);
return value.filter(
(e) => e.toLowerCase().indexOf(arg.toLowerCase()) !== -1
);
}
}

对我来说,最好的方法是在组件内部而不是在模板中使用管道。

constructor(
private filterPipe: FilterPipe
) {}
ngOnInit() {
this.filterForm.controls.nick.valueChanges.pipe(
startWith(''),
debounceTime(500),
map(value => {
this.nicks.forEach(nick => {
nick = this.filterPipe.transform(value, nick); // or what you want to do
});
})
);
}

在Stackblitz中的工作示例

HTML:

<h3>Filter:</h3>
<form [formGroup]="filterForm">
<input type="text" formControlName="nick" />
</form>
<h3>Nicks:</h3>
<div *ngFor="let nick of nicks | filterPipe: (debouncedControl$ | async)">
{{ nick }}
</div>

组件:

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
nicks: string[] = [
'Siema',
'Elo',
'Tu',
'Hdw3DCtV',
'and',
'Gównow',
'Zdzisiu11',
'Zdzisiu1',
'Zdzisiu2',
'Zdzisiu3',
'Zdzisiu4',
'Zdzisiu5',
];
constructor(private formBuilder: FormBuilder) {}
filterForm = this.formBuilder.group({
nick: [''],
});
debouncedControl$ = this.filterForm.controls.nick.valueChanges.pipe(
startWith(''),
debounceTime(500)
);
}

管:

@Pipe({
name: 'filterPipe',
})
export class FilterPipe implements PipeTransform {
transform(values: string[], inputValue: string): string[] {
return values.filter((v) => {
return (
v.toLowerCase().indexOf((inputValue || '').toLocaleLowerCase()) > -1
);
});
}
}

说了这么多,这可能不是一个场景,我将达到一个角管道。

备选组件解决方案:

@Component({
selector: 'alternate',
template: `
<form [formGroup]="filterForm">
<input type="text" formControlName="nick" />
</form>
<ul>
<li *ngFor="let nick of filteredNicks$ | async"> {{nick}} </li>
</ul>
`,
})
export class AlternateSolutionComponent {
constructor(private formBuilder: FormBuilder) {}
nicks = ['Siema', 'Elo', 'Tu'];
lowercaseIncludes(a: string, b: string): boolean {
return a.toLocaleLowerCase().indexOf(b.toLocaleLowerCase()) > -1;
}
filterForm = this.formBuilder.group({ nick: [''] });
filteredNicks$ = this.filterForm.controls.nick.valueChanges.pipe(
startWith(''),
debounceTime(500),
map((inputValue) => {
return this.nicks.filter((nick) =>
this.lowercaseIncludes(nick, inputValue)
);
})
);
}

我已经创建了一个decorator,该decorator支持调用函数

export function ngDebounce(milleseconds: number) {
let timeoutRef:any;
return function(target:Object, _: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function(...args: any[]) {
clearTimeout(timeoutRef);
timeoutRef = setTimeout(() => {
original.apply(this, args);
}, milleseconds);
}
return descriptor;
}
}

然后改变输入

的搜索变量
<input type="text" (input)="changeInput($event.target.value)" >
<div *ngFor="let nick of nicks | filterPipe: searchInput">
{{ nick }}
</div>

component.ts

searchInput: string = ''

@ngDebounce(400)
changeInput(value: string) {
this.searchInput = value
this.ref.markForCheck();
}

最新更新