In my Angular-14 application, I want to search or filter data in a table using Text Input field and select dropdown.
I am this JSON response:
{
"data": {
"pageItems": [
{
"id": "1b1b89c0-b18d-4403-b1ba-0a73c1eb2c5c",
"departmentId": "66306a0e-3369-4e5f-b8ed-d158b147d252",
"firstName": "Janet",
"lastName": "Smith",
"employeeDepartment": 1,
"employeeDepartment": {
"departmentName": "Account"
}
}
],
"pageSize": 10,
"currentPage": 1,
"numberOfPages": 1,
"totalRecord": 1,
"previousPage": 0
}
}
Then I derive the interface that is shown below.
Interface:
export interface PageItem {
id: string;
firstName: string;
lastName: string;
employeeStatus: number;
employeeDepartment: IEmployeeDepartment;
}
export interface IEmployeeDepartment {
departmentName: string;
}
export interface IData {
pageItems: PageItem[];
pageSize: number;
currentPage: number;
numberOfPages: number;
totalRecord: number;
previousPage: number;
}
export interface IEmployeeList {
data: IData;
successful: boolean;
message: string;
statusCode: number;
}
Kindly note that the Id are string (GUID from the backend)
Then I have this component.
employee.component.ts:
import { Component, ViewChild, ElementRef, TemplateRef, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { EmployeeService } from 'src/app/features/admin/services/employee.service';
import { IData, PageItem, IEmployeeList } from 'src/app/features/admin/models/employee/employee-list';
import { EMPLOYEE_STATUS_DATA } from 'src/app/core/enums/employeestatus';
declare var $:any;
@Component({
selector: 'app-employees',
templateUrl: './employees.component.html',
styleUrls: ['./employees.component.scss']
})
export class EmployeesComponent implements OnInit {
allEmployeeList: any[] = [];
employeeData: PageItem[] = this.allEmployeeList;
selectedFirstName: string = '';
selectedDepartment: string = '';
constructor(
private employeeService: EmployeeService,
private toastr: ToastrService,
) { }
ngOnInit(): void {
this.loadAllEmployees();
this.loadAllDepartments();
}
loadAllEmployees() {
this.employeeService.getAllEmployees().subscribe({
next: (allEmployeeList = res.data.pageItems;
this.employeeData = res.data.pageItems;
this.dataBk = res.data.pageItems;
},
error: (error) => {
this.toastr.error(error.message);
}
})
}
onEmployeeSearch() {
this.allEmployeeList = this.employeeData.filter(
(row) =>
row.firstName
?.toLowerCase()
.includes(this.selectedFirstName?.toLowerCase()) &&
(this.selectedStatus !== -1
? row.employeeDepartment.departmentName?.includes(this.selectedDepartment)
);
}
employee.component.html:
<div >
<div >
<div >
<div >
<label for="firstName">First Name:</label>
<input type="text" autocomplete="off" id="firstName" [(ngModel)]="selectedFirstName" (input)="onEmployeeSearch()" placeholder="First Name" />
</div>
</div>
<div >
<div >
<label for="employeeDepartment">Employee Department</label>
<ng-container *ngIf="selectedSearchCriteria == 'employeeDepartment'">
<div >
<div >
<label for="employeeDepartment">Employee Department:</label>
<ng-select [items]="employeeDepartments"
[selectOnTab]="true"
[searchable]="true"
id="employeeDepartment"
[(ngModel)]="selectedDepartment"
(change)="onEmployeeSearch()"
bindValue="id"
bindLabel="departmentName"
placeholder="Select Employee Department"
[multiple]="false"
[clearable]="true"
formControlName="departmentId">
</ng-select>
</div>
</div>
</ng-container>
</div>
</div>
</div>
</div>
<table >
<tr *ngFor="let row of allEmployeeList>
<td>{{ row?.firstName || 'N/A' }}</td>
<td>{{ row?.lastName || 'N/A' }}</td>
<td>{{ row?.employeeDepartment?.departmentName || 'N/A' }}</td>
</tr>
</table>
I am using TextInput(selectedFirstName) and Select Dropdown(selectedDepartment) for the search.
When the TextInput input or Dropdown onChange, the application should search through the table and reflect the result.
The TextInput is working, but the Select Dropdown on Change does not have any effect on the table.
How do I correct this and search the table with the Select Dropdown(selectedDepartment) onChange?
Thank you.
CodePudding user response:
Your code is looking good!, the only thing that rings a bell is the last part of this method (the condition where you filter by the selected option).
Can you give this a try?
onEmployeeSearch() {
this.allEmployeeList = this.employeeData.filter(
(row) =>
row.firstName
?.toLowerCase()
.includes(this.selectedFirstName?.toLowerCase()) &&
(this.selectedStatus === -1 ||
row.employeeDepartment.departmentName?.includes(this.selectedDepartment)
);
}
That way, using OR you'll get true for every record if there's no selected option, and if there is a selected option, you get to filter stuff.
I hope that helps!
CodePudding user response:
You can filter your data using angular pipes. Take a look at the official docs here: https://angular.io/guide/pipes