简体   繁体   中英

Angular reactive form search elements

I need your help. I am trying to search for elements: alive and on the button to search in lower and upper case. elementsArray is my array of elements, which consists of fields: id , name , price . This code doesn't give me any errors, but the search doesn't work correctly: it's empty at first, there are no items. When I enter data in input, nothing is shown either, however when I delete all the values, the array elements appear. Tell me, what is my mistake? How to make a live search and by button? Thank you very much

html

<form [formGroup]="liveForm">
   <input (input)="findElementsByName()" formControlName="findLiveElement">
</form>

<form [formGroup]="simpleForm">
   <input formControlName="findSimpleElement">
   <button>Find</button>
</form>

<div>
   <p *ngFor="let element of filteredElements">Name: {{element.name}}, price: {{element.price}}</p>
</div>

ts

import { Component, OnInit } from '@angular/core';
import {elementsArray} from "../../array";
import {FormControl, FormGroup} from "@angular/forms";

@Component({
   selector: 'app-search',
   templateUrl: './search.component.html',
   styleUrls: ['./search.component.css']
})

export class SearchComponent implements OnInit {

   public filteredElements: any[] = [];
   elements = elementsArray;
   liveForm: FormGroup;
   simpleForm: FormGroup;

   ngOnInit(): void {
     this.liveForm = new FormGroup({
       findLiveElement: new FormControl('')
     })
     this.simpleForm = new FormGroup({
       findSimpleElement: new FormControl('')
     })
    }

   findElementsByName() {
    this.liveForm.controls['findLiveElement'].valueChanges.subscribe(value => {
     this.filteredElements = this.elements;
     this.filteredElements = this.elements.filter(
      element => element.name.toLowerCase().includes(value) ||
      element.name.toUpperCase().includes(value));
     })
   }
}
<form [formGroup]="simpleForm">
   <input formControlName="findSimpleElement">
   <button  (click)="search()">Find</button>
</form>


    import { Component, OnInit } from '@angular/core';
    import {elementsArray} from "../../array";
    import {FormControl, FormGroup} from "@angular/forms";

    @Component({
       selector: 'app-search',
       templateUrl: './search.component.html',
       styleUrls: ['./search.component.css']
    })

    export class SearchComponent implements OnInit {

       public filteredElements: any[] = [];
       elements = elementsArray;
       liveForm: FormGroup;
       simpleForm: FormGroup;

       ngOnInit(): void {
         this.liveForm = new FormGroup({
           findLiveElement: new FormControl('')
         })
         this.simpleForm = new FormGroup({
           findSimpleElement: new FormControl('')
         })
         this.filteredElements=elements;
        }

      search() {
        this.filterTeredElements(
          this.simpleForm.controls['findSimpleElement'].value
        );
      }

      filterTeredElements(value) {
        this.filteredElements = this.elements.filter(
          (element) =>
            element.name.toLowerCase().includes(value) ||
            element.name.toUpperCase().includes(value)
        );
      }

      findElementsByName() {
        this.liveForm.controls['findLiveElement'].valueChanges.subscribe(
          (value) => {
            this.filterTeredElements(value);
          }
        );
      }
    }

You could check a working solution in this stackblitz .

Let's go with the code and the changes I made:

search.component.html

<form [formGroup]="liveForm">
  <input formControlName="findLiveElement" />
</form>

<br />

<form [formGroup]="simpleForm">
  <input formControlName="findSimpleElement" />
  <button (click)="search()">Find</button>
</form>

<div>
  <p *ngFor="let element of filteredElements">
    Name: {{ element.name }}, Price: {{ element.price }}
  </p>
</div>

The first thing is that I'm not using (input) event since we are using reactive forms and you could get notified about a change in the FormControl with valueChanges .
Also have included (click) event on the Find button of the second form to perform the search() .

Now in the component class:

search.component.ts

export class SearchComponent implements OnInit {
  filteredElements: any[];
  elements: any[] = elementsArray;
  liveForm: FormGroup;
  simpleForm: FormGroup;

  constructor() {}

  ngOnInit(): void {
    this.liveForm = new FormGroup({
      findLiveElement: new FormControl(''),
    });
    this.simpleForm = new FormGroup({
      findSimpleElement: new FormControl(''),
    });

    // Initialize with all the elements
    this.filteredElements = this.elements;

    // Subscribing to the changes of input
    this.liveForm.controls['findLiveElement'].valueChanges
      .pipe(
        map((value: string) => value.toLowerCase()),
        debounceTime(250),
        distinctUntilChanged()
      )
      .subscribe(
        (pattern) => (this.filteredElements = this.findElementsByName(pattern))
      );
  }

  findElementsByName(pattern: string) {
    return this.elements.filter((element) =>
      element.name.toLowerCase().includes(pattern)
    );
  }

  search() {
    const value = this.simpleForm.controls['findSimpleElement'].value;
    const pattern = value.toLowerCase();
    this.filteredElements = this.findElementsByName(pattern);
  }
}

In the ngOnInit initialize filteredElements with all the elements.
Apply a pipe to the valueChanges of liveForm that:

  • map the value and convert it toLowerCase() .
  • Apply a debounceTime(250) to avoid emitting with every key stroke.
  • Apply a distinctUntilChanged() to avoid emitting the same value consecutively.

After that subscribe to get the final search pattern and pass it to the findElementsByName method that returns an array with the filtered values according to the pattern.
Finally you have the search() method that gets executed when the user clicks in the Find button and apply a similar logic. In this method you get the value of the simpleForm , convert it toLowerCase() , and call the findElementsByName to get the filtered elements.

Feel free to ask any doubt. Hope this helps you!

PS: In the stackblitz I have used my own array of elements since I don't have yours.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM