Angular 2+: Searching in json data when search is a shared component

741 views Asked by At

the app.component has json data displayed in the view using *ngfor. User can perform search as he/she types in the search box (basically on keyup event).

For future ease, I have made this search.component as a shared component.

I have written a code and want to know if this is the correct approach or even better one exists. Please do help.

Note: Currently, the code has 7 entries, but the actual entries will be minimum 1000.

Here is my sample POC for the application.

enter image description here

search.component.html - On every character entered, calling the method getSearchString()

<input type="text" placeholder="type here to search" (keyup)="getSearchString(text)" #text>

search.component.ts - Using subject _searchText defined in a common service to emit the value.

getSearchString(text) {
  this.appService._searchText.next(text.value);
}

app.service.ts - Defining the subject being used.

 _searchText = new Subject<string>();
 getSearchText$ = this._searchText.asObservable();

app.component.ts - Subscribing on the observable getSearchText$ to search the json.

ngOnInit() {
    this.data = [
      {
        name: 'pranjal',
        id: 's1'
      }, {
        name: 'alini',
        id: 's2'
      }, {
        name: 'nishank',
        id: 's3'
      }, {
        name: 'pranvi',
        id: 's3'
      }, {
        name: 'mayuri',
        id: 's4'
      }, {
        name: 'malya',
        id: 's5'
      }, {
        name: 'pravi',
        id: 's5'
      }
    ];
    this.filteredData = JSON.parse(JSON.stringify(this.data));
    this.appService.getSearchText$.subscribe((searchText) => {
      this.filteredData = this.searchData(this.data, searchText);
    });
}

searchData(data, searchText) {
  let newData = [];
  if (!searchText) {
    newData = this.data;
  } else {
    newData = data.filter((obj) => {
      return obj.name.includes(searchText);
    });
  }
  return newData;
}
2

There are 2 answers

0
Boland On

Nothing wrong with this approach. Different ways to achieve it. In your case, you are using observables to send a notification from the search component to the service. I would do it the other way around, the search component would call a method on the search service. The search service then would publish the results in an observable.

Have you looked at the redux pattern? Can highly recommend it, especially for larger apps. I'm using ngrx in very big applications, and loving it.

2
Rahul On

Everything seems to be good - but i have some idea - you can just filter your data from the component where you have your original data in your case app.component.ts has the data so just trigger a event from the child search.component.ts and filter the data

search.component.ts

@Output() searchText = EventEmitter<any>();
getSearchString(text) {
   this.searchText.emit(text);
}

Every time when the text changes it will emit the text changes to your parent component

app.component.html

<child-component (searchText)="searchData($event)" ></child-component>

app.component.ts

searchData(event: any) {
  let newData = [];
  if (!event) {
    newData = this.data;
  } else {
    newData = this.data.filter(obj =>  obj.name.includes(event));
  }
  this.data = [...newData];
}

This will be your dynamic component whenever you use this component it will pass the search text and you can use this search component in any of your components - Please don't bind the service in your component - if you want to update the service you need to change your code - your component should be something that generates code on demand it should be something that do same action every time

Hope this helps you- Happy coding :)