【发布时间】:2020-09-02 08:36:33
【问题描述】:
我对 Angular 还很陌生,我目前正在努力在我的表单字段上显示源自我的 API 后端的错误。我的前端验证工作没有任何问题。
我已经根据this 链接设置了我的前端验证。
这是我的表单 HTML:
<form [formGroup]="createDetailsForm" (ngSubmit)="onCreate()" autocomplete="off" *ngIf="!created_customer">
<div class="modal-header">
<h5 class="modal-title">
{{'create_customer' | transloco | ucfirst}}
</h5>
<button type="button" class="close" (click)="d('Cross click')">×</button>
</div>
<div class="modal-body">
<div class="form-row">
<div class="form-group col">
<label class="form-label">{{'name' | transloco | ucfirst}}</label>
<input type="text" class="form-control" formControlName="name">
<app-control-messages [control]="createDetailsForm.get('name')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col mb-0">
<label class="form-label">{{'vatnumber_prefix' | transloco | ucfirst}}</label>
<app-countries controlName="vatnumber_prefix"></app-countries>
<app-control-messages [control]="createDetailsForm.get('vatnumber_prefix')"></app-control-messages>
</div>
<div class="form-group col mb-0">
<label class="form-label">{{'vatnumber' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="xxxxxxxxxx" formControlName="vatnumber"
pattern="[0-9]*">
<app-control-messages [control]="createDetailsForm.get('vatnumber')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col mb-0">
<label class="form-label">{{'street' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="" formControlName="street">
<app-control-messages [control]="createDetailsForm.get('street')"></app-control-messages>
</div>
<div class="form-group col mb-0">
<label class="form-label">{{'number' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="" formControlName="number">
<app-control-messages [control]="createDetailsForm.get('number')"></app-control-messages>
</div>
<div class="form-group col mb-0">
<label class="form-label">{{'suffix' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="" formControlName="suffix">
<app-control-messages [control]="createDetailsForm.get('suffix')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col mb-0">
<label class="form-label">{{'zipcode' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="" formControlName="zipcode">
<app-control-messages [control]="createDetailsForm.get('zipcode')"></app-control-messages>
</div>
<div class="form-group col mb-0">
<label class="form-label">{{'city' | transloco | ucfirst}}</label>
<input type="text" class="form-control" placeholder="" formControlName="city">
<app-control-messages [control]="createDetailsForm.get('city')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label class="form-label">{{'country' | transloco | ucfirst}}</label>
<app-countries controlName="country"></app-countries>
<app-control-messages [control]="createDetailsForm.get('country')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label class="form-label">{{'email' | transloco | ucfirst}}</label>
<input type="email" class="form-control" formControlName="email">
<app-control-messages [control]="createDetailsForm.get('email')"></app-control-messages>
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label class="form-label">{{'phone' | transloco | ucfirst}}</label>
<input type="text" class="form-control" formControlName="phone">
<app-control-messages [control]="createDetailsForm.get('phone')"></app-control-messages>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
(click)="c('Close click')">{{'close' | transloco | ucfirst}}</button>
<button type="submit" class="btn btn-primary">{{'save' | transloco | ucfirst}}</button>
</div>
</form>
因此,消息与 app-control-messages 组件一起显示。这与上一个链接中的设置完全相同。他使用默认验证器和自定义验证服务。表单组是这样设置的:
this.createDetailsForm = this.fb.group({
name: ['', Validators.required],
vatnumber_prefix: ['BE', Validators.required],
vatnumber: ['', Validators.compose([Validators.required, ValidationService.numeric])],
street: ['', Validators.required],
number: ['', Validators.required],
suffix: [''],
zipcode: ['', Validators.required],
city: ['', Validators.required],
country: ['BE', Validators.required],
email: ['', Validators.compose([Validators.required, ValidationService.emailValidator])],
phone: ['', Validators.required],
full_vatnumber: [],
});
现在问题出在下面。我创建了一个服务,我可以从来自 http post 到后端的每个错误中调用它。以下是 httpclient 错误响应的示例:
this.subs.sink = this.custService.createCustomer(value).subscribe((res) => {
this.custService.add(res);
},
(error) => {
this.serverValidation.validate(error, this.createDetailsForm);
})
Here is the errorbag I'm receiving and sending to the validate function.
验证函数:
@Input() form: FormGroup;
@Input() error: HttpErrorResponse;
constructor(private notificationService: NotificationsService) {
}
validate(error, form) {
if (error.status === 422) {
form.markAsUntouched();
form.markAsPristine();
for (var e in error.error.errors) {
let control = form.get(e);
if (control) {
control.markAsTouched();
control.markAsDirty();
control.setErrors({ 'test': true });
control.updateValueAndValidity();
} else {
return undefined;
}
}
form.updateValueAndValidity();
}
this.notificationService.error(error.statusText, error.error.message);
}
所以我试图将错误包的内容设置为特定的表单控件,但它没有显示消息。有人知道我在做什么错吗?
编辑:
按照 Ausiàs Armesto 的建议,我已将代码放在前端组件的错误函数中:
(error) => {
console.log(error);
/* TODO Translate Backend validation errors to form fields */
this.createDetailsForm.markAsUntouched();
this.createDetailsForm.markAsPristine();
for (var e in error.error.errors) {
let control = this.createDetailsForm.get(e);
if (control) {
control.markAsTouched();
control.markAsDirty();
for (var message in error.error.errors[e]) {
control.setErrors({ 'error': { message: message } })
}
} else {
return undefined;
}
}
并更改了我的验证服务以显示“错误”键的消息。现在消息显示。所以我的下一个问题是:如何将其重构为外部服务?
解决方案
在错误回调中我调用我的服务:
(error) => {
this.serverValidation.validate(error, this.createDetailsForm);
})
验证服务:
export class ServersideFormValidationService {
@Input() form: FormGroup;
@Input() error: HttpErrorResponse;
constructor(private notificationService: NotificationsService) {
}
validate(error, form) {
if (error.status === 422) {
form.markAsUntouched();
form.markAsPristine();
for (var e in error.error.errors) {
let control = form.get(e);
if (control) {
control.markAsTouched();
control.markAsDirty();
control.setErrors({ 'error': { message: error.error.errors[e][0] } })
} else {
return undefined;
}
}
}
this.notificationService.error(error.statusText, error.error.message);
}
}
【问题讨论】:
-
问题已解决。我的解决方案见上文
标签: javascript angular laravel frontend