1

I am new to angular and i want to implement a custom validator who can trim the input field of model driven approach form.i am getting some problem in implementation.when i set the value using setValue() in the validator function infinite callstack will occure. So Please suggest me how i can update the form value and one more thing i want to use validators in the way i'm using.

Validator Function

 static trimSpace(c:AbstractControl) {
        console.log(c);
        let v= c.value.replace(/\s\s+/g, ' ');
        let valid=true;
        console.log(v.trim());
        c.setValue(v);
     return true ? null : {
      trimmed: true
     }
 } 

Component Form

 this.addressForm=this.fb.group({
     firstName:['',Validators.compose([Validators.required,TrimValidator.trimSpace])]});
1
  • None of the answers given are very generic. I'd be interested to see if you found a good solution. Commented Jan 28, 2019 at 23:06

4 Answers 4

0

You shouldn't be changing values in the validation phase otherwise you may get infinite validation cycles.

this line

let v= c.value.replace(/\s\s+/g, ' '); 

should be removed, and you should create a Custom pipe to have that value altered in the template before it reaches the validator logic.

https://angular.io/guide/pipes

Sign up to request clarification or add additional context in comments.

4 Comments

c.setValue(v) is causing error .That means i have to implement pipes instead of validator
Validators are for validation. Pipes are for transforming values.
But i want to change form control value and pipe is not used to alter the value of formControl.
I want to send the trimmed data to my database .
0

Agree with @Dean but in case you still wanted to do this :

  c.setValue(v,{emitEvent:false});

If emitEvent is true, this change will cause a valueChanges event on the FormControl to be emitted. This defaults to true (as it falls through to updateValueAndValidity).

But it's a terrible idea.

Definitely create a Pipe or a directive.

1 Comment

It is still not working .can pipe will change the formcontrol value.
0

I would rely on a event here to control the behavior. So you could do in template:

(keyup)="trim(addressForm.controls.firstName.value)"

and in TS:

trim(value) {
  let val = value.replace(/\s\s+/g, ' ');
  this.addressForm.controls.firstName.patchValue(val)
}

And seem you have some type of Validation going on. You could then set a custom error to the form when you need to:

this.addressForm.setErrors({trimmed: true})

and remove it...

this.addressForm.setErrors(null)

and show the error in template if it exists:

*ngIf="addressForm.hasError('trimmed')"

5 Comments

i do not want to write trimming code in html and component. in your case i have to write this code again and again.
Well you have now mention that this should be "generic", so the answer is based on the question at hand, which would suggest this is just one case. You should always clearly state your question.
okay Sir, Sorry for inconvenience. please provide the solution.
That is my plunker link in which i made it using directive link. But in directive also i have to write that directive in html and that is not a very good approach. so that's why i want to implement it using validators.
Hmm, I understand. I just wonder if the directive is not best option though. At least at the moment I cannot see how to get rid of the looping. With valueChanges we could do {emitEvent:false}, but that doesn't help here, I tried it. I know using valueChanges is not an option here, since it wouldn't be generic either. Hmm. Tough question :)
0

Try following way :

Trim and set new value on value change event and whenever your value will get changed or set, validator function automatically get called.

import statement

function trimSpace(trimmedVal: boolean): ValidatorFn {   
  return (control: AbstractControl): {[key: string]: any} => {
    if(trimmedVal){
      return true ? null : { trimmed: true }
    }
  }; 
 }

//Component

export class  {
let trimmed: boolean = false;

//  constructor(
ngOnInit(){
    this.addressForm = this.fb.group({
        firstName:['', Validators.compose([Validators.required, trimSpace(this.trimmed)])]
    });
    this.addressForm.valueChanges.subscribe(data => this.onValueChanged(data));
}
onValueChanged(data?: any) {
    // trim value code
    if(value == trimmed){
        this.trimmed = true;
        // set value in following way
        this.addressForm..controls['firstName'].setValue('trimmedValue');
    }
}  }

4 Comments

It is not a generic way because i have to implement onValueChanged method in every Component.
Suppose i have 5 fields in form Control then how will i update formControl.
If you want then you can also use valueChange for particular field : this.addressForm.controls['firstName'].valueChanges.subscribe(data => this.someFunction(data));
I want to make a validator who can trim the input fields and we do not need to write code in our component. We just need to describe our validator name in formbuilder.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.