Search Filter Pipe is not working using ngx-pagination after click 2nd pagination number in angular 13 - angular9

This is search filter directives
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if (!items) return [];
if (!searchText) return items;
return items.filter(item => {
return Object.keys(item).some(key => {
return String(item[key]).toLowerCase().includes(searchText.toLowerCase());
});
});
}
}
Below is the HTML code with array table
<input type="search" class="col-sm-3.1 m_left16 " id="searchAll" [(ngModel)]="searchAllDataBenchmark"
placeholder="Search by keywords" autocomplete="off">
<tr *ngFor="let i of userArray2 | filter: searchAllDataBenchmark | paginate: { itemsPerPage: count, currentPage: p } ">
<pagination-controls (pageChange)="p = $event"></pagination-controls>
It's working properly when stay in 1st page in the pagination search filter is working. But when click the send page and search any table data it's not working and data table is not filtering. Data table array is showing blank.
Can any one resolve this issue which I am facing.
"ngx-pagination": "^5.1.1"

Related

Refresh datalist in view after user finishes typing in textbox Angular 7

I am trying to refresh a datalist in the view after waiting for user to finish typing in the textbox and updating results. Tried with angular directives, tried with Observable and various timeouts and debounces and no luck. I ran out of options.
In the html file:
<input type="text" class="form-control" id="Other"
(keyup)="onKeySearch($event)" list="dynamicList" formControlName="Other"/>
<datalist id="dynamicList">
<option *ngFor="let employee of employeesList" [value]="employee.Name">
{{employee.Name}}</option>
</datalist>
in the .ts file:
public employeesList: EmployeeData[] = [];
timeout: any = null;
getEmployeesList(name : string) {
let empList: EmployeeData[] = [];
// get employees list from service
this.employeeService.getEmployeesList(name).subscribe((data: any) => {
empList = data;
console.log(empList)
})
return empList;
}
public onKeySearch(event: any) {
let empListt: EmployeeData[] = [];
clearTimeout(this.timeout);
var $this = this;
this.timeout = setTimeout(() => {
empListt = $this.getEmployeesList(event.target.value);
console.log(empListt)
}, 1000);
this.employeesList = empListt;
}
The problem is that the datalist is not updates after retrieving the data an populating the list. After it exists the method the list is again empty, thus no data to display.
I have added stackblitz example code with similar code as above (same behavior):
.ts file:
import { Component, VERSION, OnInit } from "#angular/core";
import { FormControl } from "#angular/forms";
import { distinctUntilChanged, debounceTime, tap } from "rxjs/operators";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
searchControl = new FormControl("");
message = "";
public employeesList: string[] = [];
ngOnInit() {
this.searchControl.valueChanges
.pipe(
tap(() => (this.message = "User is typing...")),
distinctUntilChanged(),
debounceTime(1000)
)
.subscribe(res => {
this.message = "User finished typing!";
this.employeesList.push('1');
this.employeesList.push('2');
this.employeesList.push('3');
});
}
}
.html file:
<input [formControl]="searchControl" list="dynamicList">
<datalist id="dynamicList">
<option *ngFor="let employee of employeesList">
{{employee}}</option>
</datalist>
<span> {{message}} </span>
The dropdown will be filtered according to the text you have entered. So, in the given example, since you have pushed 1,2 and 3 values into the list, the drop down will only list with the filtered value.
Eg. if you input 1, the drop down list will have 1 (which is the required functionality)
You can see this behavior clearly if you slightly change the test input as :
ngOnInit() {
this.searchControl.valueChanges
.pipe(
tap(() => (this.message = "User is typing...")),
distinctUntilChanged(),
debounceTime(1000)
)
.subscribe(res => {
this.message = "User finished typing!";
this.employeesList.push('Employee 1');
this.employeesList.push('Employee 2');
this.employeesList.push('Employee 3');
});
}
Now, when you search 'Employee', it will list all 3, and if you search 'Employee 1', it will list the required one entry only. (Which is the expected behavior)
Your formControl (called 'Other', for some reason) has an event that is emitted as an Observable on each change. You can subscribe to that event, and use the RxJS operator debounceTime() to specify how many milliseconds should it wait for the user to stop typing until the event is emitted.
I have created a simple DEMO, maybe it's easier to understand.
Good luck!

Observable<any> Is not binding Angular 6

I have been working on another question here and the helper has gone a little quiet and I need to get a solution on this pretty quickly. See Here For More Information
I have implemented the new code and find that the array is returning 'false' to the browser:
I have mapped from the get request and then try bind commissions$ to the click-cards.component.html. This should then filter out any duplicate records and render them into groups using lodash.
Edits: based on feedback, but the result still seems to be the same
click-cards.component.ts
import { Component, OnInit } from '#angular/core';
import { Commission } from '../commission';
import { AnalyticsService } from '../analytics.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import * as _ from 'lodash';
#Component({
selector: 'app-click-cards',
templateUrl: './click-cards.component.html',
styleUrls: ['./click-cards.component.scss']
})
export class ClickCardsComponent implements OnInit {
commissions$: Observable<any>;
constructor(private analyticsService: AnalyticsService) {}
ngOnInit() {
this.getCommissions();
}
getCommissions(){
this.commissions$ = this.analyticsService.getAllCommissionData().pipe(
map((commissions: Commission[]) => {
if (commissions !== undefined && commissions !== null) {
return _.uniqBy(commissions, 'url');
}
}),
map((commissions: Commission[]) => {
commissions = _.groupBy(commissions, commission => commission.page_type);
return commissions;
})
)
}
}
I can't seem to find a way to get commissions$ to bind to the .html file:
click-cards.html
<ng-container *ngIf="commissions$ | async as commissions">
<ng-container *ngFor="let page_type of ['home', 'article','statistics', 'products']">
<h4>{{ page_type | titlecase }}</h4>
<p *ngIf="!commissions[page_type]">No {{ page_type }} Commissions Logged Yet</p>
<ul *ngFor="let card of commissions[page_type]">
<app-click-card [card]="card"></app-click-card>
</ul>
</ng-container>
</ng-container>
Does anyone know what I am doing wrong here? I don't usually work with Observables, so I normally subscribe to the service REST method and it works. So I am a little new to this process.
The map operator will allow you to transform the value of the observable source. Whatever you return there will replace the value. In the second map you return true so that's what the result value will be in the end. You should return the transformed commissions value again.

Searching in multiple columns angular2

I am using a textarea for searching a table, all in an angular2 application with bootstrap.
My code was searching in one column, now I want the search term to be looked up across two columns, and the user will see all the matched table rows highlighted.
HTML:
<input class="form-control" id="search" [(ngModel)]="searchString" type="text" placeholder="Search by Book ID.." style="float:right;"
value="">
<tr *ngFor="let books of bookDetails |jobsearch:{ bookId: searchString} : false | paginate: { itemsPerPage: 50, currentPage: p };">
The other column that I want to be searched is 'bookName'.
Custom pipe example:
#Pipe({
name: 'booksearch'
})
export class BookSearchPipe implements PipeTransform {
transform(items: Array<any>, filter: {[key: string]: any }): Array<any> {
return items.filter(item => {
let noMatch = Object.keys(filter)
.find(key => item[key] !== filter[key]);
return !noMatch;
});
}
}
Usage:
<tr *ngFor="let books of bookDetails |booksearch:{ bookId: searchString, bookname: searchString }”>

Multiple parameters on Angular Filter Pipe

Ok, so the problem I am having here now is that I am trying to put multiple filters on a pipe for a search result page, where the data is being extracted from an api. How exactly do I incorporate different parameters to this filter pipe?
Link to app: https://stackblitz.com/edit/flight-example?file=app%2Fapp.component.html
Here is the Pipe logic:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any, max_price: any, depature_city: any): any {
if (max_price === undefined) return 0;
// Filter each
return items.filter(t=> {
// For Maximum Price
if (t.price.amount <= max_price) {
return t;
}
// For Depature City, also where I am having trouble
if (depature_city && items.depature.city.toLowerCase().indexOf(depature_city.toLowerCase()) === -1){
return false;
}
else{
return items;
}
})
}
}
Here is the HTML :
<div>
<label> Maximum Price </label>
<input type="text" [(ngModel)]="max_price">
<label> Depature City </label>
<input type="text" [(ngModel)]="depature_city">
<p>Result:</p>
<ul>
<li *ngFor="let group of displayItems | filter: max_price:depature_city">
City: {{group.departure.city}} <br>
Price : {{group.price.amount}}
<ul>
<li *ngFor="let flight of group.segments">
Flight No: {{flight.flightNumber}}
</li>
</ul>
</li>
</ul>
</div>
This is the last time I am going to post a question about this app I swear.
You need to modify your logic to filter from both conditions and return,
export class FilterPipe implements PipeTransform {
transform(items: any, max_price: any, depature_city: any): any {
if (max_price === undefined) return 0;
var filtereditems : any = [];
// Filter each
if (max_price){
filtereditems = items.filter(t=>t.price.amount <= max_price);
}
if(depature_city){
console.log("departure city",depature_city);
filtereditems = items.some(t=> t.departure.city.includes(depature_city));
}
if(depature_city && max_price){
console.log("departure city",depature_city);
filtereditems = items.find(t=> t.departure.city.includes(depature_city));
}
console.log("filtered",filtereditems);
return filtereditems;
}
}
The above code needs to be checked, it just applies the logic

Angular2 Auto suggester

I have been searching a lot on INTERNET but still unable to figure out how i can make custom auto suggester without any third party. After a lot of google I found this
but the issue is that my response from api is a bit different i am getting response as :
[{"id":"1","name":"aa"},{"id":"2","name":"bb"}...]
due to which i am getting [object][object] as value in pipe.
Can anyone please help how i can handle this request with this pipe. I want that their should be a text box on whose click there should be listing and on user input the below suggestions may vary.
Pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
return el.toLowerCase().indexOf(input) > -1;
})
}
return value;
}
}
in ts:
import { Component } from '#angular/core';
import {FilterPipe} from './pipes'
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title:String;
names:any;
constructor(){
this.title = "Angular 2 simple search";
this.names = ['Prashobh','Abraham','Anil','Sam','Natasha','Marry','Zian','karan']
}
}
*** this works perfectly but in my case this.name array is deferent as told above.
Given the fact that the data source is an array of objects, to be dynamic I will use the following pipe that will iterate each object for values, then if a match is found will keep the object for display:
Pipe
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter',
pure: false
})
export class FilterPipe implements PipeTransform {
transform(items: Array<any>, filter: string): any {
if (!filter) {
return items;
}
return items.filter(item => {
for (let field in item) {
if (item[field] === null || item[field] === undefined){
continue;
}
if (item[field].toString().toLowerCase().indexOf(filter.toLowerCase()) !== -1) {
return true;
}
}
return false;
}
);
}
}
HTML
<input type="text" [(ngModel)]="search" placeholder="Filter...">
<div *ngFor="let item of datasource | filter:search"></div>
Look at pure: false declaration of the pipe. This tells the pipe to filter continuously the data, so if you have a service that is dynamically pushing data into your datasource, your filtered display will update automatically. Also using a pipe like this you can filter on all values of your objects and objects can change structure dynamically without impact on your filter.
You can try something similar like below
<input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">
<ul>
<li *ngFor="let n of list | FilterPipe: queryString : searchableList ">
{{n.name}} ({{n.id}})
</li>
</ul>
pass required field to be searched
this.searchableList = ['name','id']
pipe
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string,searchableList : any) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
var isTrue = false;
for(var k in searchableList ){
if(el[searchableList[k]].toLowerCase().indexOf(input) > -1){
isTrue = true;
}
if(isTrue){
return el
}
}
})
}
return value;
}
}
You can update the pipe according to your needs.