2

I have the following Angular component:

  private json: JsonResponseDTO;

  constructor(private dtoService: PoolDTOServiceService) {
  }

  ngOnInit() {
    this.dtoService.setJsonResponse();
    this.getPool();
  }

  getPool() {
    this.json = this.dtoService.jsonResponse;
  }

The json contains an element pools, that is an array. This one should be filtered by name, which is typed in an input. (I don not show the HTML, since this is not relevant).
I want to be able to 'remove' my search criteria, so the initial approach is:

  private json: JsonResponseDTO;
private filterJson: JsonResponseDTO;

  constructor(private dtoService: PoolDTOServiceService) {
  }

  ngOnInit() {
    this.dtoService.setJsonResponse();
    this.getPool();
  }

  getPool() {
    this.json = this.dtoService.jsonResponse;
    this.filterJson = this.json;
  }

  filter(filterCriteria: String) {
    this.filterJson = this.json;
    this.filterJson.pools.filter((element) => element.name === filterCriteria);
  }

and then bind the filterJson to the HTML DOM.
Is there a cleaner way to do this? I want to avoid requesting the new JSON each time the filtered name is 'removed', since the data is expensive in time to fetch.

8
  • 1
    Are you just want to know is this a fine way or not? Commented Jan 17, 2019 at 9:11
  • I want to know if someone sees a cleaner way, because copying an array seems not right to me Commented Jan 17, 2019 at 9:11
  • If you don't want to request new JSON then filter is the only option you can do. Commented Jan 17, 2019 at 9:14
  • here is many copying of json response. why it is so? try to use observable with behaviour subject in service. so when you need you can filter this at the component side. Commented Jan 17, 2019 at 9:16
  • the clean way i think is to add a get method on the backend that take filterCriteria as parameter and try to add pagination Commented Jan 17, 2019 at 9:16

2 Answers 2

3

You can use a pipe for filtering it will be much cleaner, just add the pipe in front of *ngFor directive.

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  transform(value: any, field: string, input: string) {
    if (input !== undefined && input.length >= 2) {
      input = input.toLowerCase();
      if (typeof value[0] === 'string') {
        return value.filter(function(el: any) {
          return el.toLowerCase().indexOf(input) > -1;
        });
      }
      return value.filter(function(el: any) {
        return el[field].toLowerCase().indexOf(input) > -1;
      });
    }
    return value;
  }
}

Add this pipe, and in HTML where ever you need to filter

<div *ngFor="let val of filterJson | filter: "filterCriteria""> </div>

from change detection and performance point of view, pipes are awesome. Hope this helps, all the best

Sign up to request clarification or add additional context in comments.

1 Comment

@DhananjaiPai lol no, since the DOM needs to be rendered once the list is updated its much more economical to handle this via pipes, (Pipes are pure, managing change detection via same is much more easier)
1
filter(filterCriteria: String) {
    this.filterJson = {...this.json, pools: pools.filter((element) => element.name === filterCriteria);
}

You could potentially write it a bit cleaner by using spread and changing the pools property as above.

I'm assuming you should keep a cached copy of the original 'this.json' for a case when the filters are reset.

2 Comments

yea, thats my primary concern, how to 'restore' the original when the filter is removed
Again, assuming you are using filterJson to display the pool in the UI and you want to get the original data back when filter is cleared, you can simply do this.filterJson = {...this.json} to revert back to the original response and have angular rerender

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.