4

I have a situation where I need to format the user input and then validate it.

I am using a reactive form and created my custom validation as seen below (relevant parts):

HTML:

<input type="text" formControlName="invoiceNumber" (blur)="formatInvoiceNumber()" class="form-control">
<div *ngIf="this.form.controls['invoiceNumber'].invalid && this.form.controls['invoiceNumber'].touched">Invalid Text</div>

Controller:

this.form = this.formBuilder.group({
            'invoiceNumber': ['', validateInvoiceNumber()],
        });

    formatRoNumber() {
            var invoiceNumber = this.form.controls['invoiceNumber'].value;
            //format invoice number
        }

Validator:

export function validateInvoiceNumber(): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
        let invoiceNumber = control.value,
            isValid = true;

        //validate invoice number
        return isValid ? null : { validInvoiceNumber: { valid: false } }
    };
}

I am running into timing issues. The formatting of input happens after validation.

How can I tell Angular to apply the formatting and then validate?

8
  • 1
    Looks like you are formatting on blur ... so when the user leaves the field. By default, validation occurs as the user types. So you want it to validate when the user leaves the field instead? Then consider not using the built in validation (not specifying it in the FormBuilder) and instead just calling it directly. If you want it to occur after the formatting, you could call it from formatInvoiceNumber(). Commented Apr 18, 2017 at 21:17
  • @DeborahK, I see. I was hoping there was a way to make this work with FormBuilder...or run the formatting some other way. thank-you Commented Apr 18, 2017 at 21:23
  • If you want to format as they type, you could add a watch on valueChanges and format/validation then. Commented Apr 18, 2017 at 22:14
  • You could also decide to validate on blur using the technique shown here: stackoverflow.com/questions/33866824/… Commented Apr 18, 2017 at 22:17
  • @DeborahK, could you please show how to call validation directly on an input element as you explain in your first comment? Commented Apr 20, 2017 at 18:28

3 Answers 3

1

You can do this with formbuilder if you also use ngModel in order to format. I've accomplished it like so

<ion-input
formControlName="fullName"
type="text"
[ngModel]="fullName | pipeHere"
(ngModelChange)="fullName=$event">
</ion-input>

this.customerFields = this.fb.group({
  fullName: ['', Validators.compose([ Validators.required, Validators.minLength(11) ])]
});

the (ngModelChange) will be what fires your pipe into action while the validation fires as usual. If you write a custom pipe, you can allow for additional validation as well.

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

Comments

0

Caleb's way is not working for me for some reason, and the validator is being called twice as much.

If it helps anyone, I ended up doing it this way. There must be a better way, seems odd to setValidators, apply them, then remove them for next updates...but this works.

Thank-you Caleb and Deborah for you help.

Control:

<input type="text" formControlName="invoiceNumber" (blur)="updateAndValidateInvoiceNumber()" class="form-control">

Controller:

updateAndValidateInvoiceNumber(): void {
     let control: AbstractControl = this.form.controls['invoiceNumber'];
     let newVal = this.invoiceFormatterPipe.transform(control.value);

     control.patchValue(newVal);
     control.setValidators(validateInvoiceNumber());
     control.updateValueAndValidity();
     control.clearValidators();
 }

Comments

0

In your formgroup, add the below pattern for that formControl:

-variable_name: ['', [Validators.pattern(/^[.\d]{1,15}$/)]]

Comments

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.