Angular 2 add debounce function directly to pipe
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I've written a pipe that filters out an array of objects based on a given query. It works great but what I'd like to do is add a debounce function to this pipe directly, instead of adding it to the input's keyup event, if possible.
I've been looking around for a solution but can't seem to find anything that's specific to what I'm looking for.
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string): any {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
Any ideas on how I would implement this in this pipe?
angular typescript debouncing angular2-pipe
add a comment |
I've written a pipe that filters out an array of objects based on a given query. It works great but what I'd like to do is add a debounce function to this pipe directly, instead of adding it to the input's keyup event, if possible.
I've been looking around for a solution but can't seem to find anything that's specific to what I'm looking for.
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string): any {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
Any ideas on how I would implement this in this pipe?
angular typescript debouncing angular2-pipe
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44
add a comment |
I've written a pipe that filters out an array of objects based on a given query. It works great but what I'd like to do is add a debounce function to this pipe directly, instead of adding it to the input's keyup event, if possible.
I've been looking around for a solution but can't seem to find anything that's specific to what I'm looking for.
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string): any {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
Any ideas on how I would implement this in this pipe?
angular typescript debouncing angular2-pipe
I've written a pipe that filters out an array of objects based on a given query. It works great but what I'd like to do is add a debounce function to this pipe directly, instead of adding it to the input's keyup event, if possible.
I've been looking around for a solution but can't seem to find anything that's specific to what I'm looking for.
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string): any {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
Any ideas on how I would implement this in this pipe?
angular typescript debouncing angular2-pipe
angular typescript debouncing angular2-pipe
asked Oct 31 '16 at 7:45
ChrillewoodzChrillewoodz
11.7k1349103
11.7k1349103
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44
add a comment |
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44
add a comment |
2 Answers
2
active
oldest
votes
The debounce or delay functions are async, in this case you need to return a promise or an observable from your pipe and use the async pipe. I created a simple example to show you how to do that with observable.
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
Plunker
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
add a comment |
Lets imagine a scenario where a text field performs a 'search-as-you-type' job. In order to log meaningful search text, component should wait until typing comes to an end.
The correct way to set a delay time to pipe execution should be as follows (See the comments in the code):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return ;
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40338233%2fangular-2-add-debounce-function-directly-to-pipe%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The debounce or delay functions are async, in this case you need to return a promise or an observable from your pipe and use the async pipe. I created a simple example to show you how to do that with observable.
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
Plunker
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
add a comment |
The debounce or delay functions are async, in this case you need to return a promise or an observable from your pipe and use the async pipe. I created a simple example to show you how to do that with observable.
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
Plunker
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
add a comment |
The debounce or delay functions are async, in this case you need to return a promise or an observable from your pipe and use the async pipe. I created a simple example to show you how to do that with observable.
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
Plunker
The debounce or delay functions are async, in this case you need to return a promise or an observable from your pipe and use the async pipe. I created a simple example to show you how to do that with observable.
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
Plunker
answered Oct 31 '16 at 9:29
BazingaBazinga
6,40332649
6,40332649
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
add a comment |
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
Nice, I'll try it out and see how it works.
– Chrillewoodz
Oct 31 '16 at 10:04
1
1
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
Doesn't this just add a delay between the input and the output rather than debouncing (wait x amount after the last input before processing)?
– 0xcaff
Nov 24 '16 at 2:42
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
How can we estimate the delay value ? lets say I have 10 000 items (less or more in my case)
– HDJEMAI
Dec 28 '17 at 4:03
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
I've just tested this solution but it does not speed up the filter in my case, I don't know how to approach this problem.
– HDJEMAI
Dec 28 '17 at 4:06
add a comment |
Lets imagine a scenario where a text field performs a 'search-as-you-type' job. In order to log meaningful search text, component should wait until typing comes to an end.
The correct way to set a delay time to pipe execution should be as follows (See the comments in the code):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return ;
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
add a comment |
Lets imagine a scenario where a text field performs a 'search-as-you-type' job. In order to log meaningful search text, component should wait until typing comes to an end.
The correct way to set a delay time to pipe execution should be as follows (See the comments in the code):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return ;
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
add a comment |
Lets imagine a scenario where a text field performs a 'search-as-you-type' job. In order to log meaningful search text, component should wait until typing comes to an end.
The correct way to set a delay time to pipe execution should be as follows (See the comments in the code):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return ;
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
Lets imagine a scenario where a text field performs a 'search-as-you-type' job. In order to log meaningful search text, component should wait until typing comes to an end.
The correct way to set a delay time to pipe execution should be as follows (See the comments in the code):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return ;
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
edited Nov 16 '18 at 20:50
answered May 17 '18 at 20:50
Omer GurarslanOmer Gurarslan
37616
37616
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40338233%2fangular-2-add-debounce-function-directly-to-pipe%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Where you want to apply the debounce
– Bazinga
Oct 31 '16 at 8:17
@PatrickJane Not sure where it needs to go.
– Chrillewoodz
Oct 31 '16 at 8:27
Why do u need the debounce?
– Bazinga
Oct 31 '16 at 8:39
@PatrickJane So it doesn't filter a list of potentially hundreds of items on every keystroke..
– Chrillewoodz
Oct 31 '16 at 8:44