Home > Net >  Angular creating filter with pipe and map
Angular creating filter with pipe and map

Time:10-12

I am fairly new to angular and I am trying to create a filter for a value.

In my component - I have => myData$: Observable<MyInterface>

and the interface is as follows

export class FoundValues {
    customerName: string;
    startDate: string;
    endDate: string;
    includes(values: string) : boolean {
      value = value.toLowerCase();
      return this.valueIncludes(this.customerName, value);
    }

    private valueIncludes(includedValue, value){
       if (value) {
         const value = value.toLowerCase().includes(includedValue);
         return result;
       } else {
          return false;
       }
    }
}
export interface MyInterface {
    found_values : Array<FoundValues>;
}

In my component ngOnInit(), I am trying to create a logic filter but not getting it as it return a type FoundValues[] and it's complaining that it's not the expected Observable return type.

export class MyComponent implements OnInit{
      myData$ = Observable<MyInterface>;
      myControl = new FormControl();

     ngOnInit(): void{
        this.filterData = 
        this.myControl.valueChanges.pipe(map(value=>this._filter(value)));
     }
     private _filter(value:string): .....{
         --- need logic here ----
     }
}

How can I create the filter so that if I type a customer name in my form it shows only the matching customer name?

CodePudding user response:

You can use the combineLatest RxJS operator for filtering through as shown in the following code snippet,

export class MyComponent implements OnInit {
  myData$ = Observable < MyInterface > ;
  mySearchQuery$: Observable < any > ;
  searchString = new FormControl('');

  filterData: Observable < any >

    constructor() {
      mySearchQuery$ = this.searchString.valueChanges.startsWith('');
    }

  ngOnInit(): void {
    this.filterData = this.searchQuery$.combineLatest(this.myData$).map(([queryString, listOfCustomers]) => {
      return listOfCustomers.filter(customer => customer.name.toLowerCase().indexOf(queryString.toLowerCase()) !== -1)
    })
  }
}

The combineLatest RxJS operator takes in the observables myData$ and mySearchQuery and returns the observable filterData containing the emitted values that match the searchString.

CodePudding user response:

usual design in angular would be different

https://stackblitz.com/edit/angular7-rxjs-pgvqo5?file=src/app/app.component.ts

interface Entity {
  name: string;
  //...other properties
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = new FormControl('');
  data$: Observable<Array<Entity>> = of([
    { name: 'Jhon' },
    { name: 'Jane' },
    { name: 'Apple' },
    { name: 'Cherry' },
  ]);

  filtered$: Observable<Array<Entity>>;

  ngOnInit() {
    // this can be moved to a util lib/file
    const startWithPipe = pipe(
      map(
        ([query, data]: [query: string, data: Array<Entity>]): Array<Entity> =>
          data.filter((entity) =>
            query ? entity.name.toLowerCase().startsWith(query) : true
          )
      )
    );

    this.filtered$ = this.name.valueChanges.pipe(
      startWith(''),
      debounceTime<string>(300),
      withLatestFrom(this.data$),
      startWithPipe
    );
  }
  • Related