Home > Net >  Angular Filtering: Problem when i Clear the Search Box
Angular Filtering: Problem when i Clear the Search Box

Time:12-04

I Have a list of objects that i'm displaying, and i added a search box to filter a column, now when i enter a value, it works fine and the data is filtered. The problem is, when i clear the search box, i don't get all the data back, i stay stuck with what i searched first, so i have to refresh every time i want to change the entered value or get the whole list.

Here's my Ts Code :

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Facture } from '../model/facture.model';
import { FactureService } from '../services/facture.service';

@Component({
  selector: 'app-factures',
  templateUrl: './factures.component.html',
  styleUrls: ['./factures.component.css']
})
export class FacturesComponent implements OnInit {
  factures?: Facture[]; //un tableau de chînes de caractères
  cat?: number;

  constructor(private factureService: FactureService, private router: Router) {
    // this.factures = factureService.listeFacture();
  }

  deleteFacture(p: Facture) {
    let conf = confirm("Etes-vous sûr ?");
    if (conf)
      this.factureService.deleteFacture(p.idFacture).subscribe(() => {
        console.log("facture supprimé");
      });
    this.router.navigate(['factures']).then(() => {
      window.location.reload();
    });
  }
  
  search() {
    if (this.cat != null) {
      this.factures = this.factures?.filter(res => {
        return res.idFacture.toLocaleString().match(this.cat!.toLocaleString())
      });
    } else if (this.cat == null) {
      this.ngOnInit();
    }
  }


ngOnInit(): void {
  this.factureService.listeFacture().subscribe(prods => {
    console.log(prods);
    this.factures = prods;
  });

}

}

Here's my Html Code :

<body >
<main role="main"  >
<div   style="background-color: white;">
  <h2>Liste des Adhérents</h2>
  <input type="text" [(ngModel)]="name" (input)="Search()" />  
  <table >
    <thead >
<tr>
   <th>Nom Complet</th>
   <th>Grade</th>
   <th>Poste</th>
   <th>Telephone</th>
   <th>E-mail</th>
   <th></th>
 </tr>
 </thead>

     <tr *ngFor="let item of adherents">
       <td>{{item.nomcomplet}}</td>
       <td>{{item.grade}}</td>
       <td>{{item.poste}}</td>
       <td>{{item.telephone}}</td>
       <td>{{item.email}}</td>
       <td><button [routerLink]="['/adherents/', item.id]" style="margin-right: 0.2em;" title="Details" ><i ></i></button>
        <button [routerLink]="['/adherentEdit/', item.id]"
        style="margin-right: 0.2em;" title="Modifier" ><i ></i></button></td>
     </tr>
   </table>

   
</div>
</main>
</body>

Please how can i modify The Search() Function so i can dynamically get data from the Array when changing the value in the search box input ?

CodePudding user response:

You say: "when i clear the search box, i don't get all the data back.." You don´t specify whether you receive 0 items, or you stay with what you received with the previous filter.

  1. If you recibe the same items than the previous search, I guess that you are passing to search something in "cat" that the code doesn't get as 'null' but is not null ('' or undefined, or something), so it doesn't enter to the second if.

So the solution would be delete the second if:

if (this.cat != null) {
      this.factures = this.factures?.filter(res => {
        return res.idFacture.toLocaleString().match(this.cat!.toLocaleString())
      });
    } else {
      this.ngOnInit();
    }

On the other hand, if you are getting as far as invoking the "onInit()", probably your view is not detecting the change and is not refreshing the values of the array. This is because Angular's change detection does not pay attention to the arrays/objects (which are passed by reference) and therefore does not re-render it.

I guess that this is the problem, and you can do a quick test adding an "impure" pipe as slice:

<tr *ngFor="let item of adherents | slice:0">

EXTRA: Perhaps this may also have something to do with your problem, although I don't think so. In any case, as a tip, I would not use directly the ngOnInit method, which is part of the Angular lifecycle.

You could pass all its logic to a function , invoke it in ngOnInit, and then always invoke the new function instead ngOnInit. Something like this:

ngOnInit(): void {
 this.getAndSetFactures()
}

getAndSetFactures() {
 this.factureService.listeFacture()
   .subscribe(prods => {
    console.log(prods);
    this.factures = prods;
  });
}

  search() {
    if (this.cat != null) {
      this.factures = this.factures?.filter(res => {
        return res.idFacture.toLocaleString().match(this.cat!.toLocaleString())
      });
    } else {
      this.getAndSetFactures();
    }
  }

CodePudding user response:

This is happening because you are assigning to the same array that contains all of your data when you filter.

I would solve this by introducing a second variable that holds the original data, and another array that keeps the filtered data:

export class FacturesComponent implements OnInit {
  factures?: Facture[]; //un tableau de chînes de caractères
  facturesFiltrèes: Facture[];


  ngOnInit(): void {
    this.factureService.listeFacture().subscribe(prods => {
      console.log(prods);
      this.factures = prods;
    });
  }
  
  search() {
    this.facturesFiltrèes = this.factures.filter(res => 
      !this.cat || res.idFacture.toLocaleString().match(this.cat!.toLocaleString()));
  }

}

From now on, use facturesFiltrèes where you need to display the search results, not just factures (because this is the one we reserve for keeping the original data pristine).

P.S.: Please don't call ngOnInit yourself, this is an Angular lifecycle method which should only be called once by the framework itself.

  • Related