I am in situation like, to pass array of objects (productlists) as parameter for custom validator. But it shows error like "only single value can be passed as parameter".
<div class="formGroup">
<input
formControlName="productname"
matInput
#input
type="text"
[matAutocomplete]="auto"
class="form-control"
(click)="clicked(input)"
(input)="performFiltering(input)"
/>
<mat-autocomplete
#auto="matAutocomplete"
(optionSelected)="onProductChange1($event)"
>
<mat-option
*ngFor="let product of filteroptions | async"
[value]="product.productname"
>
{{product.productname}}
</mat-option>
</mat-autocomplete>
<div *ngIf="productdetailsarray.at(i).get('productname')?.errors?.['productnotavailable'] && productdetailsarray.at(i).get('productname')?.touched">
<span style="font-size: 10pt; color:red">Product is not valid</span>
</div>
My ts code is
export interface productentity{
productname:string,
price:number,
gst:number,
}
productlists = [
{ productname: 'apple', price: 10, gst: 10 },
{ productname: 'orange', price: 20, gst: 12 },
{ productname: 'lemon', price: 30, gst: 20 },
{ productname: 'grape', price: 60, gst: 20 },
{ productname: 'bringal', price: 25, gst: 20 },
{ productname: 'tomato', price: 40, gst: 20 },
{ productname: 'kiwi', price: 120, gst: 20 },
{ productname: 'potato', price: 500, gst: 20 }];
productlist!:productentity[];
filteroptions!: Observable<productentity[]>;
productname: new FormControl('', [Validators.required,Productavailable(productlists)]),
ngOnInit() {
this.productlist = this.productlists.sort((a:any,b:any)=> {
return a.productname < b.productname ? -1 : a.productname > b.productname ? 1 : 0
});
}
clicked(input: any) {
if (input.value) {
this.performFiltering(input);
}
else{
this.filteroptions = of(this.productlist);
}
}
performFiltering(input: any) {
if (input.value) {
this.filteroptions = of(this._filter(input.value));
} else {
this.filteroptions = of(this.productlist);
}
}
private _filter(value: string): productentity[] {
const searchvalue = value.toLocaleLowerCase();
return this.productlist.filter((option) =>
option.productname.toLocaleLowerCase().includes(searchvalue)
);
}
My custom validator function is
export function Productavailable(val: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
let productvalue: string = control.value;
let productlists = [
{ productname: 'apple', price: 10, gst: 10 },
{ productname: 'orange', price: 20, gst: 12 },
{ productname: 'lemon', price: 30, gst: 20 },
{ productname: 'grape', price: 60, gst: 20 },
{ productname: 'bringal', price: 25, gst: 20 },
{ productname: 'tomato', price: 40, gst: 20 },
{ productname: 'kiwi', price: 120, gst: 20 },
{ productname: 'potato', price: 500, gst: 20 }];
const selectedProduct = productlists.find(
(product) => product.productname === productvalue
);
if (productvalue=='') {
return null;
}
if (selectedProduct==null) {
return { 'productnotavailable': true, 'requiredValue': val }
}
return null;
}
}
Here I am facing the situation to add the 'productlists" array object both in component ts and in custom validator function( ). Due to this i cant able to provide productlists as dynamically. Can someone help me how pass array object as parameter to custom validate function or any other solution to display error message if the product is not available in the productlist.
NOTE about "bind" to complementary the other answer.
When you create a custom validator you can use a function that return a validator
validator(products:any[]){
return (control: AbstractControl): ValidationErrors | null => {
..inside you can use "products" variable
}
}
And you use the validator like
productname: new FormControl('', [Validators.required,
this.validator(this.productlists))),
But this only works if "this.productList" not change after you create the formControl,
e.g.
//you can NOT use
this.productList=['one','two']
control=new FormControl('',this.validator(this.productList))
this.productList=['one','two','three']
//because inside the validator "products" are ALWAYS ['one','two']
You use "bind(this)" if the variable can change after you create the formControl -then you can use all the variables of the component inside the validator function using "this."+variable_of_component