1

I'm working on a users module that has a users view for administrative purposes. I can see my data, so that works fine, but I'm not understanding how the search filter is supposed to work. The following is my code. I'm a novice to typeScript and Angular so I'm using examples from online, but failing. SMH! Anyway, I type into the search filter and nothing happens.

users.component.ts

import { Component, OnInit, ViewChild, Input } from '@angular/core';
import { FormControl } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { Router } from "@angular/router";
import { UserService } from '../../users/user.service';
import { MatInput } from "@angular/material/input";
import { MatSort } from '@angular/material/sort';
import { BehaviorSubject } from "rxjs";
import { Observable } from 'rxjs';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.scss']

})

export class UsersComponent implements OnInit {
  public users: any[] = [];  
  searchControl = new FormControl();
  filteredOptions: Observable<string[]>;  
  MatTableDataSource: Observable<string[]>;

  resetUsers: any;
  @Input() header = "Users View";  
  @Input() columns = [
    { userName : "User Name" },
    { firstName: "First Name" },
    { lastName: "Last Name" },
    { phone: "Phone" }, 
    { email: "Email" },    
  
  ];
  @Input() data: any[]; 
  @ViewChild(MatInput, { static: false }) search: MatInput;
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  displayData = [];
  
constructor(   
    private userService: UserService,    
    private httpClient: HttpClient
  ) { }

dataSource = new MatTableDataSource<string[]>();
  
 
  ngOnInit(): void {    
    this._getUsers();    
    
  }

  ngAfterViewInit() {
    this.userService.getUsers().subscribe(data => {
      this.users = data.users;  
    });   
    this.search.stateChanges.subscribe(() => {
      this.displayData = [];
      this.users.forEach((entry) => {        
        if (entry.header.toLowerCase().includes(this.search.value.toLowerCase()))
        {
        this.displayData.push(entry);       
        }
      });
    });
  }

  
  
  private _getUsers()
  {    
    this.userService;
    this.userService.getUsers().subscribe(data => {
      this.users = data.users;  
    }); 
  }


}

user.component.html

<form>
  <mat-form-field>
    <div class="search-input">
      
        <mat-label>Search</mat-label>
        <input type="text"
               matInput               
               [matAutocomplete]="auto" />
      
    </div>
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
        {{option}}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

<div class="users">
  <app-extend-table [header]="header"
                       [data]="users"
                       [columns]="columns">
  </app-extend-table>  
</div>

Dan
  • 59,490
  • 13
  • 101
  • 110

2 Answers2

0

I'm no familiar with Angular Material but I see you are pushing the filtered values to the displayData, but displayData isn't used anywhere, at least from the code you have shown. What you could do instead is use displayData as the data input of your table:

  <app-extend-table [header]="header"
                   [data]="displayData"
                   [columns]="columns">
  </app-extend-table>  

and when you get your users you also feed displayData:

this.userService.getUsers().subscribe(data => {
  this.users = data.users;  
  this.displayData = data.users; 
});  

this.userService.getUsers().subscribe(data => {
  this.users = data.users;  
  this.displayData = data.users;  
}); 

Another approach would be create a filter pipe (https://angular.io/guide/pipes) to filter the data of your table, that would look like this: Filter:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "filterTable"
})
export class FilterTablePipe implements PipeTransform {
  constructor() {}

  transform(rows: any[], search: string): any {
    // here you gonna have to create the filter
    // I'm assuming row has a property name, which would be the user name
    return rows.filter(row => row.name.includes(search));
  }
}

And on HTML:

  <app-extend-table [header]="header"
                   [data]="users | filterTable: searchValue"
                   [columns]="columns">
  </app-extend-table>  

Where searchValue is the value typed by the user, you gonna have to create this variable.

Here's one example of a list of dates being filtered by an input. It's not the same but might help you understand: https://stackblitz.com/edit/angular-ivy-filter-date-list?file=src%2Fapp%2Fapp.component.html.

Important: You probably need to call renderRows (Calling renderRows() on Angular Material Table) after updating the list.

0
<div class="search-box-v1">
<app-search from="SEARCH_PRODUCTS"(filterEvent)="applyConfigProductFilter($event)"
(reloadEvent)="refreshConfigProductList($event)">
</app-search> </div>
applyConfigProductFilter(filterValue: string) {
        filterValue = filterValue.trim(); // Remove whitespace
        filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
        this.configProductDataSource.filter = filterValue;
        this.displaySearchRecords = filterValue != '';
}


selector: 'app-search', SearchComponent

if you want to need below component then i will share you sure.

Darshan Malani
  • 478
  • 3
  • 12