Search code examples
htmlangularformssearchfilter

Reset list in mat-select


I work on angular app and i have problem and i dont know how to resolve it. To begin in app, its about search filters. When i select an option, my select change when i click again on the button (mat-form-field), I have the selected option and not all element in list (that i have before). I think is in the filterUsers() but i need this line because an other button exist to change the year and filter other users. I try to explain this better as possible but tel me if isnt clear, So is the code:

Component.ts :

ngOnInit(): void {
this.dataService
  .getInterviewYearGrouped()
  .pipe(
    take(1),
    switchMap(years => {
      this.yearFilterList = years;
      this.searchForm.controls.mainFilters.controls.interviewYear.setValue(this.yearFilterList[0]);
      return this.dataService.getUsers({ interview_year: this.searchForm.controls.mainFilters.value.interviewYear });
    })
  )
  .pipe(take(1))
  .subscribe((users: UserNineBox[]) => {
    this.users = users;
    this.originalJobSuggestions = this.users.map(u => u.job);
  });

this.searchForm.controls.mainFilters.controls.interviewYear.valueChanges
  .pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap(year => this.dataService.getUsers({ interview_year: year }).pipe(catchError(() => of([])))),
    takeUntil(this._destroyed),
    catchError((err, caught) => caught)
  )
  .subscribe((users: UserNineBox[]) => {
    this.users = users;
    this.filterUsers();
  });

this.searchForm.valueChanges
  .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this._destroyed))
  .subscribe(() => this.filterUsers());

this.internalClassification.valueChanges
  .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this._destroyed))
  .subscribe(() => this.filterInternalClassification());

this.job.valueChanges
  .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this._destroyed))
  .subscribe(() => this.filterJobSuggestions());


private filterUsers(): void {
this.filteredUsers = this.users.filter(u => {
  return (
    includeQuery(u.job, this.searchForm.controls.hiddenFilters.controls.job.value) &&
    includeQuery(u.internalClassification, this.searchForm.controls.hiddenFilters.controls.internalClassification.value) &&
    this.filterByPerson(u) &&
    this.filterByAdminStructure(u)
  );
});
this.jobSuggestions = new Set(this.filteredUsers.map(u => u.job));
this.originalJobSuggestions = this.jobSuggestions; <-- this line cause the problem 
this.internalClassificationSuggestions = new Set(this.filteredUsers.map(u => u.internalClassification));
this.originalInternalClassificationSuggestions = this.internalClassificationSuggestions;
this.nameSuggestions = new Set([...this.filteredUsers.map(u => u.firstname), ...this.filteredUsers.map(u => u.lastname)]);
this.submitUsers.emit(this.filteredUsers);

And this is HTML with my button job list:

<mat-form-field appearance="outline" floatLabel="never" class="filter">
  <mat-select formControlName="job" placeholder="{{'gpec.ninebox.job' | translate}}">
    <input
      matInput
      (keydown)="$event.stopPropagation()"
      [formControl]="job"
      placeholder="{{'search' | translate}}"
      class="mat-select-filter"
    />
    <mat-option *ngIf="!jobSuggestions?.length" disabled>{{'label.no.data' | translate}}</mat-option>
    <mat-option *ngIf="jobSuggestions?.length" (click)="resetHiddenFilter('job')">-</mat-option>
    <mat-option *ngFor="let job of jobSuggestions" [value]="job" (click)="setSearchFilterTags('job', 'recruitment.offer', job)">
      {{ job }}
    </mat-option>
  </mat-select>
</mat-form-field>

Solution

  • The problem is that the line of code in the filterUsers() function assigns jobSuggestions to originalJobSuggestions. As a result, after applying the filter, jobSuggestions contains only selected values. When you click on the (mat-form-field) button again, only the selected values are displayed, not the entire list.

    To solve this problem, you can try to keep a copy of the original job offers before filtering. Example:

    private filterUsers(): void {
      const originalJobSuggestions = new Set(this.users.map(u => u.job));
    
      this.filteredUsers = this.users.filter(u => {
        // ...
      });
    
      // ...
    
      this.jobSuggestions = new Set(this.filteredUsers.map(u => u.job));
      this.originalJobSuggestions = originalJobSuggestions;
      // ...
    }
    

    This way, the original job offers will remain unchanged and available for the list even when the filter is activated. Remember to use a copy of originalJobSuggestions when resetting filters to restore the full list.