Angular 7 custom validation with dynamic/updated param
Asked Answered
S

3

6

I am using angular 7 with material design components

I have requirement to add requireMatch validation to mat-autocomplete.

I have created custom validation with param but param value does change dynamically.

Below is my component code.

this.stepFormGroup = this.formBuilder.group({
    AccessCode: ["", [Validators.required, this.requireMatch(this.accessCodeList)]]
});

////require-match validation for access-code
requireMatch = (accessCodes: string[]) => {
    return (control: FormControl) => {
        const selection: any = control.value;
        console.log("accessCodes", accessCodes, "selection", selection);
        if (accessCodes.indexOf(selection)===-1) {
            return { requireMatch: true };
        }
        return null;
    }
}

Issue i am facing that i am always getting empty(init) in accessCodes inside requireMatch.

Changes of this.accessCodeList does not reflect to validator.

Meaning after changing this.accessCodeList it doesn't get updated array in requireMatch validator.

So anyone have any idea about how to pass dynamic param in custom-validator?

Sapphira answered 21/3, 2019 at 13:58 Comment(13)
Can you provide stackblitz/Aishaaisle
And also the question is not clear--) Just describe what you want? and what currently not workingAishaaisle
It's working fine: stackblitz.com/edit/angular-9nggzxRadiation
I think, you need use, when change "this.accessCodeList", this.stepFormGroup.get('AccessCode').setValidators([Validators.required, this.requireMatch(this.accessCodeList)])Reflex
I fogot, use this.stepFormGroup.get('AccessCode').updateValueAndValidity() after change the validatorReflex
@Reflex I used above code after value of this.accessCodeList changes. Still not getting updated list in validatorSapphira
If this.accessCodeList changes you have to set Validators again.Radiation
@Radiation Can you tell me how to change set validator of specific field again with updated value?Sapphira
see stackblitz.com/edit/angular-pxez4f?file=src/app/… (You has a type error, index can be 0 when match with the first element)Reflex
Here is a working solution: stackblitz.com/edit/angular-9nggzxRadiation
@Reflex I have updated question. my issue i am not getting updated this.accessCodeList in validatorSapphira
@MullisS, change the condition, it's not accessCodes.indexOf(selection), is accessCodes.indexOf(selection)<0Reflex
@Radiation Your example worked. Thanks.Sapphira
P
5

You need to bind the validation function when you call it like this otherwise validator function will not bind the input accessList

[Validators.required, this.requireMatch(this.accessCodeList).bind(this)]

Also if you want to restrict some word in the field you can have a look one of my npm package here https://www.npmjs.com/package/ng4-validation

Padang answered 21/3, 2019 at 14:47 Comment(2)
This provide a way to access all params of component. Thanks man!Sapphira
Strangely my passed variable remains null.Buss
E
4

To make your validator function with the latest value in the controller, you can pass it as a function and resolve whenever it is required. so your validator function will get the latest or current value.

Below code will give some insight on my answer

// Component 
this.stepFormGroup = this.formBuilder.group({
    AccessCode: ["", [Validators.required, this.requireMatch(() => this.accessCodeList)]]
});

//Validator Function
requireMatch = (getAccessCodes: (() => string[])) => {
    return (control: FormControl) => {
        const selection: any = control.value;
        const accessCodes = getAccessCodes();
        console.log("accessCodes", accessCodes, "selection", selection);
        if (accessCodes.indexOf(selection)===-1) {
            return { requireMatch: true };
        }
        return null;
    }
}
Enos answered 23/1, 2020 at 12:3 Comment(0)
A
1

As per my assumption, you want to compare user input with the string array with the FormControl. So you can get the index of an item and check if it is not equal to -1 like:

var index = accessCodes.indexOf(selection);
if (index != -1) { // That means item found in the array
  console.log('if')
  return { requireMatch: true };
}
else {
  // console.log('esle')
  return null;
}

TS Code:

import { Component, Inject, OnInit } from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';

@Component({
  selector: 'select-multiple-example',
  templateUrl: 'select-multiple-example.html',
  styleUrls: ['select-multiple-example.css'],
})
export class SelectMultipleExample implements OnInit {
  public stepFormGroup: FormGroup;
  accessCodeList: any[] = ['Prashant', 'Pimpale'];

  constructor(private fb: FormBuilder) {

  }

  public ngOnInit(): void {
    this.stepFormGroup = this.fb.group({
      AccessCode: ["", [Validators.required, this.requireMatch(this.accessCodeList)]]
    });
  }

  ////require-match validation for access-code
  requireMatch = (accessCodes: string[]) => {
    return (control: FormControl) => {
      const selection: any = control.value;

      console.log("accessCodes", accessCodes, "selection", selection);
      var index = accessCodes.indexOf(selection);
      if (index != -1) {
        console.log('if')
        return { requireMatch: true };
      }
      else {
        // console.log('else')
        return null;
      }
      return null;
    }
  }
}

HTML Code:

<input [formControl]="stepFormGroup.get('AccessCode')">

StackBlitz

Aishaaisle answered 21/3, 2019 at 14:17 Comment(4)
I think that the problem is that Ankur want change the accessCodeList AFTER create the form. So he must use setValidatorsReflex
@Reflex Yes, might be! Asked him about clarification but he didn't respondAishaaisle
Yes. I know value will change on search since component is auto-completeSapphira
@AnkurAkvaliya Please edit the question and state your requirementsAishaaisle

© 2022 - 2024 — McMap. All rights reserved.