What is the best way to connect a search filter to a list component in Angular?

I have created a search function along with a list and filter feature.

Check out my search bar with the filter function:

<div>
  <mat-form-field class="example-full-width">
    <input matInput #message maxlength="256" 
      placeholder="Search for a vehicle" (input)='filter(message.value)' >
        <mat-hint align="start"><strong>Find a vehicle</strong> </mat-hint>
        <mat-hint align="end">{{message.value.length}} / 256</mat-hint>
  </mat-form-field>
</div>

This is the list I have:

 <div>
  <mat-nav-list>
    <mat-list-item *ngFor="let stuff of vehicleDetails">
       <a matLine> {{ stuff.name }} </a>
       <button mat-icon-button id="btn" (mouseover)="showInfo(stuff)">
          <mat-icon>info</mat-icon>
       </button>
    </mat-list-item>
  </mat-nav-list>

</div>

Both of these are part of the same .html file and share a component.ts file. The list is populated by calling getVehicleDetails() in ngOnInit.

export class VehiclelistComponent implements OnInit {
vehicleDetails: VehicleDetail[] = [];

constructor(private vehicleService: VehicleService) { }

  ngOnInit() {
    this.getVehicleDetails();
    }


 getVehicleDetails(): void {
   this.vehicleService.getVehicleDetails()
   .subscribe(vehicleDetails => {
  this.vehicleDetails = vehicleDetails;
   });
 }

Here is the filtering function I am using:

filter(searchToken: string) {
  if (searchToken == null) {
    searchToken = '';
  }
  searchToken = searchToken.toLowerCase();
  return this.vehicleDetails.filter((elem: VehicleDetail) => 
         elem.name.toLowerCase().indexOf(searchToken) > -1);
  }

I'm having issues with the filter function as it doesn't seem to be affecting my list. Any suggestions on how to fix this?

Answer №1

Have you considered using the (keyup) event instead of (input) and then re-binding your array with the result of the filter function instead of returning it from your method?

For example:

<div>
    <mat-form-field class="example-full-width">
        <input matInput #message maxlength="256" 
          placeholder="Type vehicle name" [ngModel]="message.value" (keyup)='filter($event)' >
            <mat-hint align="start"><strong>Find vehicle</strong> </mat-hint>
            <mat-hint align="end">{{message.value.length}} / 256</mat-hint>
    </mat-form-field>
</div>

And in your TypeScript file:

filter(ev: any) {
let searchToken = ev.target.value;

  if (searchToken == null) {
    searchToken = '';
  }
  searchToken = searchToken.toLowerCase();
this.message.value = searchToken; //Update UI value
  this.vehicleDetails = this.vehicleDetails.filter((elem: VehicleDetail) => 
         elem.name.toLowerCase().indexOf(searchToken) > -1); // Update array

  }

One suggestion is to work on a cloned version of your original array rather than modifying the original one directly.

For instance:

export class VehiclelistComponent implements OnInit {

vehicleDetails: VehicleDetail[] = [];
vehicleDetailsCloned: VehicleDetail[] = [];

constructor(private vehicleService: VehicleService) { }

  ngOnInit() {
    this.getVehicleDetails();
    }


 getVehicleDetails(): void {
   this.vehicleService.getVehicleDetails()
   .subscribe(vehicleDetails => {
  this.vehicleDetails = vehicleDetails;
this.vehicleDetailsCloned = [ ...vehicleDetails]; //cloned with spread operator
   });
 }


filter(searchToken: string) {
  if (searchToken == null) {
    searchToken = '';
  }
  searchToken = searchToken.toLowerCase();
  this.vehicleDetails = searchToken.length>0 
        ? this.vehicleDetailsCloned.filter((elem: VehicleDetail) => 
                   elem.name.toLowerCase().indexOf(searchToken) > -1)
        :  this.vehicleDetailsCloned ;

  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The 'replace' property is not found in the 'string' type

I am encountering a perplexing error code TS2339: Property 'X' is not found on type 'Y'. How can I resolve this issue? I have included libraries in my 'tsconfig.jsonc' file: "compilerOptions": { "target": "es3", // "es3" ...

Is it possible to include multiple eventTypes in a single function call?

I have created a function in my service which looks like this: public refresh(area: string) { this.eventEmitter.emit({ area }); } The area parameter is used to update all child components when triggered by a click event in the parent. // Child Comp ...

Unable to access attributes of an undefined value (current state is undefined)

After completing a small project, I attempted to deploy it on Vercel. The project runs smoothly without any errors on my local machine. However, when I tried to run it on the server, I encountered the following error: "Cannot read properties of undefined ( ...

Tips for preventing duplicate entries in an AG Grid component within an Angular application

In an attempt to showcase the child as only 3 columns based on assetCode, I want to display PRN, PRN1, and PRN2. Below is the code for the list component: list.component.ts this.rowData.push( { 'code': 'Machine 1', &apo ...

Passing generics to ComponentProps in TypeScript React: What is the best approach?

Scenario I have a Tree component with props defined using a generic type T: type ITreeProps<T> = ICollapsibleTreeProps<T> | INonCollapsibleTreeProps<T>; The component is implemented as follows: const Tree = <T extends {}>(props: ...

TS2347: Type arguments cannot be used with untyped function calls

In my bar.ts file, I have the following declarations: declare var angular:any; declare var _:any; declare var $:any; declare var moment:any; declare var ng:any; declare var require:any; And in my bootstrap.ts file, I reference the necessary typings: /// ...

Updating a variable in another component in Angular 5

My MainContainer has a SubContainer that houses another SubContainer (Playlist in a side panel). Within the MainContainer, I open a popup with a similar Playlist from the side panel - essentially it's the same component, but with more items. I aim to ...

Where should an EventListener be added in an Angular Service Worker?

I am currently in the process of developing an Angular Progressive Web Application (PWA) with offline capabilities. While I have made significant progress, I am facing challenges regarding events for the service worker. Specifically, I am unsure about wher ...

Class-validator: eliminate a field during validation depending on the value of another field

When using class-validator in conjunction with NestJS, I have successfully implemented the following: export class MatchDeclineReason { @IsString() @IsEnum(MatchDeclineReasonType) @ApiProperty() type: MatchDeclineReasonType; @ValidateIf(reason = ...

Convert an array with three dimensions into a two-dimensional array that includes tuples with two immutable string values

Consider the array below with multiple dimensions: type ParsedLine = [string, string]; type ParsedLines = [ParsedLine, ParsedLine] const myArray: (ParsedLine | ParsedLines)[] = [ ['something', 'somethingElse'], [['foo', & ...

Add the location of the scss file to enable server side rendering using webpack

While deploying Angular Universal for my Angular 5 application (recently migrated from Angular 4), I came across an issue with the server-side rendering option: ng build --aot --app 1 The path for variables in my SCSS files worked on the client side but ...

Managing the browser's "back" button functionality in React

I am currently using "react-dom-router v6.3.0" (strictly!) and I am struggling to figure out how to manage the browser's "back" button functionality. Specifically, I want to be able to detect when the user clicks the back button so that I can display ...

Tips for retrieving the angular route parameters from the URL?

I'm working with an Angular route that looks like this: /Chapter/:chapterId/Section/:sectionId. Let's say I have a URL such as: http://server.com/Chapter/1/Section/2?search=moby. Is there a way to extract the parameters and query string in Angu ...

Having trouble inserting the current time into Firebase Firestore

Currently, I am looking to use the current time as an input in Firebase Firestore (timestamp). Initially, when using the code snippet below: today: number = Date.now(); everything appeared to function correctly. However, the time was only updated once, s ...

Underscore Typing in the Style of Scala

Just for kicks, I started tinkering with creating a Scala-inspired underscore in typescript. I aim to simplify writing code by replacing .map(x => x.myProp) with just .map(_.myProp). The logic behind this is quite simple using Proxies, but the challenge ...

Developing bespoke styles in Angular Material 2

I am in the process of developing a unique theme for my Angular 2 application, incorporating various components from angular material 2. Despite searching extensively online, I haven't been able to find much relevant information. The only documentati ...

Combine several .ts files into one bundle called package.js

Here is the structure of my code: Foo.ts: export module Foo { export function load() { } } Bar.ts: export module Bar { export function load() { } } webpack.config.js: const path = require('path'); module.exports = { entry: { ...

Unexpected behavior with lists in Django templates

When I loop through my users' groups in a profile view to insert different sections of the page, they are not equating as expected. Here is the template: {{ user_groups }} {% for g in user_groups %} {{ g }} {% if g == "client" %} cli ...

Add content to the current position of the text input field in Ionic 2 by placing

I'm currently developing a simple calculator app and I'm facing an issue. My goal is to add text at the caret position of an input text field when a button is clicked. However, the code snippet provided below is not functioning as expected: At ...

Exploring the application of Action types within the useReducer function

In this code snippet, a reducer is being used in React's useReducer export const customReducer = (state: CustomState, action: Action) => { const { data, type } = action switch (type) { case 'updated_input': { const { value, ...