0

I have the following code:

HTML:

<div [class]="new_workflow_row_class" id="new_workflow_row">
    <div class="col-sm-6">
        <label class="checkmark-container" i18n>New Workflow
            <input type="checkbox" id="new-workflow" name="new-workflow" [(ngModel)]="new_checkbox" (click)="uncheckBox($event, 'edit')"> 
            <span class="checkmark" id="new-workflow-checkmark" [class]="checkmark_class"><span id="new-workflow-checkmark-content"></span>{{checkmark_content}}</span>
        </label>
        <input type="text" *ngIf="new_checkbox" id="new_workflow_name" name="new_workflow_name" (keyup)="clearWorkflowError(true)" [(ngModel)]="new_workflow" placeholder="Enter Workflow Name">
        <p [hidden]="!show_workflow_error && !workflowForm.errors" class="workflow-error" i18n>The workflow name already exists. Please use a different name.</p>
    </div>
</div>

Component.ts:

duplicateWorkflowValidator(control: FormControl) {
    console.log("this validator was called!");
    clearTimeout(this.workflowTimeout);

    return new Promise((resolve, reject) => {
        if (this.new_workflow != '') {
            this.workflowTimeout = setTimeout(() => {
                this
                    .requestService
                    .findWorkflow(control.value)
                    .subscribe((results: any) => {
                        let data: any = results.data;

                        if (data.duplicate) {
                            resolve({ duplicateWorkflow: { value: control.value}})
                        }
                        else if (results.status == "OK") {
                            resolve(null);
                        }
                    })
                ;
            }, 500);
        }
        else {
            resolve(null);
        }


    })

}

Inside constructor for component.ts:

this.workflowForm = new FormGroup({
    name: new FormControl(this.new_workflow, [
        Validators.required,
    ], this.duplicateWorkflowValidator.bind(this))
});

I am trying to bind this asynchronous validator to the reactive form but it's not working. I want to use the duplicateWorkflowValidator inside workflowForm and have it trigger an error message when it finds a duplicate workflow.

How do I a) bind the validator to the reactive form properly, b) access the validator errors? Thanks in advance, hopefully this makes sense.

3
  • Your code looks correct. Do you get any error? Commented Dec 5, 2017 at 2:26
  • yes, the validation errors are giving me the "required" error even when the field is not empty. Commented Dec 5, 2017 at 2:30
  • Have you tried setting the debugger; before the if and step through it? Commented Dec 5, 2017 at 2:31

1 Answer 1

1

You are mixing template forms with reactive forms. Chose one approach. In the below example I am using reactive forms.

Try this simplified version. For demonstration purposes below the validator will fail when I type test, but succeed when I type anything else. You will need to change that to your service call.

https://angular-sjqjwh.stackblitz.io

Template:

<form [formGroup]="myForm">
    <div>
        <div>
            <input type="text" formControlName="name">
            <div *ngIf="myForm.controls.name.hasError('duplicateWorkflow')">
                Workflow already exists!
            </div>
            {{ myForm.controls.name.hasError('duplicateWorkflow') | json }}
        </div>
    </div>
</form>

Component

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  workflowTimeout: number = 0;
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      name: new FormControl('', 
        [Validators.required], 
        this.duplicateWorkflowValidator.bind(this))
    });
  }

  duplicateWorkflowValidator(control: FormControl) {
    console.log("this validator was called!");

    return new Promise((resolve, reject) => {
      if (control.value === 'test') {
        this.workflowTimeout = setTimeout(() => {
          resolve({ duplicateWorkflow: { value: control.value } })
        }, 500);
      }
      else {
        resolve(null);
      }
    });
  }
}
Sign up to request clarification or add additional context in comments.

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.