How to display custom error message from custom authentication function in angular 4?

Please consider the following custom validator function, which calls an API on the server to get some data, checks it against the current form input, and returns an error if the current form input is a duplicate value:

//check to see if the new category name entered is already in the system
categoryNameUnique(c: FormControl) {
    let categoryNameAlreadyExists: boolean = false;

    //get list of current categories from the server.
    return this.inventoryCategoryService.getAll().map(items => {
        for (let item of items) {
            if (item.Name == c.value) {
                categoryNameAlreadyExists = true;                    
                break;
            }
        }

        if (categoryNameAlreadyExists) {
            //name is not unique
            return { categoryNameUnique: false }
        }
        //not a duplicate, all good
        return null;
    });
}

      

You will see that this function returns an observable (since I need to go back to the backend to get some data to check). The validator works like a charm, no problem. However, I don't know how to display an appropriate message to the user when this validator is returned incorrectly in my respective HTML view. If this function did not return an observable, I would do something like:

<div *ngIf="form.controls['categoryName'].errors?.categoryNameUnique">
    This category name is already taken
</div>

      

However, since this is an observable that is returned, the Error objects have properties exposed by the Observable, namely operator

and source

, not the custom object that I return ( {categoryNameUnique: false}

).

Any help would be appreciated.

Update 1:

Hi everyone, after trying a few other things I was able to figure out my own problem.

I set up my form like this:

constructor(private fb: FormBuilder, private router: Router, private inventoryCategoryService: InventoryCategoryService) {
    this.form = fb.group({
        'categoryName': [null, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(50), this.categoryNameUnique.bind(this)])]
    });
}

      

The required, minLength and maxLength validators are synchronous, but my custom validator category, NameUnique, is asynchronous and therefore must be compiled separately. I changed the setting to this below and everything is fine now:

constructor(private fb: FormBuilder, private router: Router, private inventoryCategoryService: InventoryCategoryService) {
    this.form = fb.group({
        'categoryName': [null, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(50)]),
            Validators.composeAsync([this.categoryNameUnique.bind(this)])]
    });
}

      

+3


source to share


1 answer


I think your problem might be how you are applying the asynchronous validator to the control. Based on your usage form.controls.categoryName

, I am assuming you are using formbuilder to create the form. In this case, you need to provide async validators as the 3rd parameter in the group's params array, for example:

this.form = this.formBuilder.group({
  categoryName: ["", [], [categoryNameUnique]]
});

      

Once you set it up like this, you should be able to see it in errors as you expect.



My preferred way of displaying custom validation errors is as follows:

<div *ngIf="form.controls.categoryName.hasError('categoryNameUnique')">
    The category name is not unique!
</div>

      

+2


source







All Articles