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));
})
}
}
CodePudding user response:
<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);
}
);
}
}
CodePudding user response:
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 ittoLowerCase()
.- 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.