Reputation: 515
too many hours wasted because of this bug. I wrote a custom validation that makes sure that the "currency name" is not repeated, the custom validation function called "validateNameUniqness" is calling a http service from a laravel api.
laravel must determine if the name is repeated or not: if name is not repeated then laravel will return true, else it will return an error message. in both cases laravel will mark the response with the status "200".
laravel code:
public function validateCurrencyNameUniqness($name){
$request = new Request();
$request->replace(['name' => $name]);
$validator = Validator::make($request->all(),[
'name' => 'unique:currencies',
]);
if ($validator->fails()) {
$uniqness_error = $validator->errors()->first('name');
return response()->json($uniqness_error, 200);
}
return response()->json(true, 200);
}
angular service will call the laravel api and return Promise:
validateCurrencyNameUniqness(name:string): Promise<any>{
return
this.http.get('http://127.0.0.1:8000/api/validateCurrencyNameUniqness/'
+ name)
.toPromise()
.then(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
angular custom validation function will return null if name is not repeated, else it will return an object:
validateNameUniqness(control: FormControl ): {[key: string]: any} {
let name = control.value;
if(name){
// if name is valid return null, else return error object
this.services.validateCurrencyNameUniqness(name)
.then(result =>{
if(result !== true){
this.unqiness_msg = result;
console.log(this.unqiness_msg );
return {'not_unique': {value: true}}
//return {'not_unique': true};
}
})
.catch(error => console.log(error));
}
return null;
}
angular material & html script:
<mat-form-field>
<input type="text" matInput #currency_name maxlength="30" placeholder="Currency Name" required [(ngModel)]="currency.name" name="name" [formControl]="name" (readystatechange)="validateNameUniqness(name)">
<mat-hint align="end">{{currency_name.value?.length || 0}}/30</mat-hint>
<mat-error *ngIf="name.invalid && (name.dirty || name.touched)">{{getErrorMessage()}}</mat-error>
</mat-form-field>
<mat-form-field>
the validation call:
name = new FormControl('', [Validators.required,this.validateNameUniqness.bind(this)]);
getErrorMessage() {
if(this.name.hasError('not_unique'))
return this.unqiness_msg;
if (this.name.hasError('required') || this.symbol.hasError('required') || this.decimals_after_point.hasError('required'))
return 'You must enter a value';
}
I think that the validation form is never be "Invalid" for the uniqueness validation. testing showing that the custom validation function is logging the error message to the console if the name is repeated, but it never show the error message to the user!
any help is appreciated.
Upvotes: 0
Views: 280
Reputation: 2487
you have some small issues in your validator
your code should look like this (this is my custom validator implementation)
export const buidUsermameValidator = (service: UserService, oldUsername?: string) => (username: FormControl): ValidationErrors | null => {
if (username && username.value !== "" && username.value !== oldUsername) {
return service.usermameExist(username.value).toPromise()
.then((result) => {
if (result) {
return { "exist": true }
}
return null
})
.catch(err => { return null })
} else {
return Promise.resolve(null)
}
}
when you going to use your validator your code should look like this
this.userForm = this.fb.group({
"username": ["", Validators.compose([Validators.required]), buidUsermameValidator(this.service)],
})
Upvotes: 1
Reputation: 19569
For one, this needs to be an async validator, check that if you didn't do it already. For two, your validator function is not returning anything. Return that promise you get from service.
if (name) {
// if name is valid return null, else return error object
return this.services.validateCurrencyNameUniqness(name)
Also, do not forget to also return from both .then
and .catch
handlers.
Upvotes: 0