如何使用angular8在电子邮件和传真的循环项目中显示每一行的验证错误 [英] How to show validation error for each row for email and fax for loop items using angular8

查看:66
本文介绍了如何使用angular8在电子邮件和传真的循环项目中显示每一行的验证错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有引导程序的Angular8,我已将输入设为来自循环数组.如果电子邮件或传真号有任何验证错误,则抛出验证错误,然后,如果第一行中有电子邮件错误,第二行中有传真错误,则显示在第三行,如果电子邮件中有错误输入错误且正确无误,第一行验证错误也将消失.但是我想对所有行显示验证错误,分别关于传真或电子邮件有错误.

HTML:

 < input type ="text"class ="form-control"占位符=电子邮件"名称=收货人";formControlName =收件人";* ngIf ="data.value.deliveryMethodId == 178"(focusout)="validationErrorOnFocusOut('emailvalid',data)'";[ngClass] =&; {'is-invalid':电子邮件已提交&&data.controls.recipients.errors}".pattern ="^ \ w +([\ .-]?\ w +)* @ \ w +([\ .-]?\ w +)*(\.ww {2,3})+ $"autocomplete ="off">;< div * ngIf =(通过电子邮件提交&& data.controls.recipients.errors)"class ="invalid-feedback"< div * ngIf ="(通过电子邮件提交的&&&&&&&&&& amp;"电子邮件)>请输入有效的电子邮件</div></div>< input type ='text'prefix =< +1"mask ="(000)000-0000";class ="form-control"占位符=收件人"名称=收货人";formControlName =收件人";* ngIf ="data.value.deliveryMethodId == 179"maxLength ="18".(focusout)="validationErrorOnFocusOut('fax',data)'";autocomplete =关闭";[ngClass] =" {'is-invalid':faxsubmitted&&data.controls.recipients.errors.mask}"< div * ngIf ="提交的传真&&数据控制收件人错误掩码class ="invalid-feedback"< div * ngIf ="提交的传真&&data.controls.recipients.errors.mask",请输入有效的传真号码</div></div> 

TS:

  public validateErrorOnFocusOut(name,data){if(name ==" emailvalid"){如果(data.controls.recipients.status ===有效"){this.emailsubmitted = false;} 别的 {this.emailsubmitted = true;}如果 (data.controls.recipients.value ==="||data.controls.recipients.value === null){this.emailsubmitted = false;}} else if(name =="fax"){如果(data.controls.recipients.status ===有效"){this.faxsubmitted = false;} 别的 {this.faxsubmitted = true;}如果 (data.controls.recipients.value ==="||data.controls.recipients.value === null){this.faxsubmitted = false;}}} 

DEMO

解决方案

您已经使用 FormBuilder 正确设置了表单.我的解决方案将专注于表单的反应性

下面是我采取的步骤

  1. 删除 [disabled] 属性上的绑定 https://stackoverflow.com/a/58831653/13680115 如果您确实包含 [disabled] 属性
  2. ,则会在控制台中引发以下警告

 看起来您正在使用带有反应形式指令的Disabled属性.如果将Disabled设置为true当您在组件类中设置此控件时,disabled属性实际上将在DOM中设置为你.我们建议使用这种方法来避免检查后更改"错误.例子:形式=新的FormGroup({首先:new FormControl({value:'Nancy',disabled:true},Validators.required),最后:new FormControl('Drew',Validators.required)}); 

  1. 删除 onChange 事件处理程序.取而代之的是我们的 ngOninit 函数.我们将注意表单值的更改,并对此做出反应以禁用适当的控件

  this.printListControl.valueChanges.管道(uniqueUntilChanged(),tap((controls:any [])=> {controls.forEach(({{mail,deliveryMethodId},index)=> {const control = this.printListControl.at(index);如果(邮件){control.get("deliveryMethodId").enable({control.get(收件人").enable({} 别的 {//为了更好的用户体验,我不会在下面两行中添加.控制.get("deliveryMethodId").setValue(null,{control.get(收件人").setValue(null,{emitEvent:false});control.get("deliveryMethodId").disable({control.get(收件人").disable({}//console.log(deliveryMethodId);控制.get(收件人").setValidators(this.getRecipientsValidation(deliveryMethodId));});})).订阅();}getRecipientsValidation(deliveryMethodId){返回+ deliveryMethodId === 178?[Validators.pattern(this.emailPattern),Validators.required]:+ deliveryMethodId === 179?[Validators.minLength(10),(10),验证者]:[Validators.required];} 

现在,每当更改 mail 值时,就会启用或禁用 deliveryMethodId 收件人控件

我们还根据选择的交付方式更新验证器

  1. 从html中删除模式验证.我们将使用 Validators.pattern

我们可以声明模式

  emailPattern =/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/; 

  1. 从模板中删除 validationErrorOnFocusOut 的事件

  2. 由于我们删除了模板验证,因此可以使用 Validator 静态类

 让printList = this.printListArray.map(x => {const {deliveryMethodId} = x;返回this.fb.group({id:x.id,名称:x.name,邮件:x.mail,电子产品:x.electronics,deliveryMethodId:x.deliveryMethodId,收件人:[x.收件人,{验证者:deliveryMethodId === 178?[Validators.pattern(this.emailPattern),Validators.required]:deliveryMethodId === 179?[Validators.minLength(10),Validators.maxLength(10),验证者]:[Validators.required],updateOn:模糊";}]});}); 

我们正在分别对每个控件进行验证,以避免它们对其他控件的影响

  1. 最后,我们的html将是这样的

 < div class ="custom-control custom-checkbox"* ngFor ="让exampleForm.get('printList').controls的数据;令j =索引"formArrayName =" printList>>< div [formGroupName] ="j">< table class ="table table-print table-borderless">< tbody>< tr>< td范围=行";class ="width90"> {{data.value.name}}</td>< td class ="width50"><输入type ="checkbox"name =邮件"formControlName ="邮件"/></td>< td class ="width50"><输入type ="checkbox"名称=电子"formControlName =电子"./></td>< td class ="width100"><选择class ="custom-select"formControlName ="deliveryMethodId";name ="deliveryMethodId"tabindex ="1"(change)="dropdownSelection(j)".>< option value = null>选择一个</option><选项* ngFor ="letletTypeType of DeliveryMethod"[值] ="agencyType.id";>{{agencyType.label}}</选项></select></td>< td class ="width200">< ng-容器* ngIf =" data.value.deliveryMethodId == 178"<输入类型=文本";class ="form-control"占位符=电子邮件"名称=收货人";formControlName =收件人";* ngIf ="data.value.deliveryMethodId == 178"[ngClass] =" {{is-invalid':data.get('recipients').invalid&&data.get('recipients').touched}';autocomplete ="off">;< div class ='invalid-feedback'* ngIf ="data.get('recipients').invalid'>请输入有效的电子邮件</div></ng-container>< ng-容器* ngIf =" data.value.deliveryMethodId == 179"<输入类型=文本";prefix =" + 1"class ="form-control"placeholder ="(###)###-####"formControlName =收件人";name =收件人"autocomplete =关闭";* ngIf ="data.value.deliveryMethodId == 179"mask ="(000)000-0000";[showMaskTyped] ="false";[ngClass] =" {'is-invalid':data.get('recipients').invalid&&data.get('recipients').touched}';>< div class ='invalid-feedback'>请输入有效的传真号码</div></ng-container>< ng容器* ngIf =" data.value.deliveryMethodId!='178'&&data.value.deliveryMethodId!='179'><输入类型=文本";class ="form-control"占位符=收件人"名称=收货人";[ngClass] =" {'is-invalid':data.get('recipients').invalid&&data.get('recipients').touched}';formControlName =收件人";/>< div class ='invalid-feedback'>必填项</div></ng-container></td></tr></tbody></table></div></div> 

此处演示

i am using Angular8 with bootstrap, i have made inputs to be from a loop array. If there is any validation error for email or fax number, it is throwing validation error, then if there is error for email in the first row, if there is any error for fax in second row it shows, if in the 3rd row if email is entered wrongly and made correct, the first row validation error also goes off. But i want to show validation error for all rows of there is an error with respect to fax or email respectively.

HTML:

              <input type="text" class="form-control" placeholder="Email" name="Recepient"
                          formControlName="recipients" *ngIf="data.value.deliveryMethodId == 178"
                          (focusout)="validationErrorOnFocusOut('emailvalid',data)"
                          [ngClass]="{ 'is-invalid': emailsubmitted  && data.controls.recipients.errors}"
                          pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" autocomplete="off">
              <div *ngIf="(emailsubmitted && data.controls.recipients.errors)" class="invalid-feedback">
                <div *ngIf="(emailsubmitted && data.controls.recipients.errors)">
                  Please enter valid email</div>
              </div>
              <input type='text' prefix="+1 " mask=" (000) 000-0000" class="form-control"
                          placeholder="Recepient" name="Recepient" formControlName="recipients"
                          *ngIf="data.value.deliveryMethodId == 179" maxLength="18"
                          (focusout)="validationErrorOnFocusOut('fax',data)"
                          autocomplete="off"
                          [ngClass]="{ 'is-invalid':faxsubmitted && data.controls.recipients.errors.mask}">
              <div *ngIf="faxsubmitted && data.controls.recipients.errors.mask" class="invalid-feedback">
                <div *ngIf="faxsubmitted && data.controls.recipients.errors.mask">Please enter valid fax number
                </div>
              </div>

TS:

  public validationErrorOnFocusOut(name, data) {
    if (name == "emailvalid") {
      if (data.controls.recipients.status === "VALID") {
        this.emailsubmitted = false;
      } else {
        this.emailsubmitted = true;
      }
      if (
        data.controls.recipients.value === "" ||
        data.controls.recipients.value === null
      ) {
        this.emailsubmitted = false;
      }
    } else if (name == "fax") {
      if (data.controls.recipients.status === "VALID") {
        this.faxsubmitted = false;
      } else {
        this.faxsubmitted = true;
      }
      if (
        data.controls.recipients.value === "" ||
        data.controls.recipients.value === null
      ) {
        this.faxsubmitted = false;
      }
    }
  }

DEMO

解决方案

You have set up your form correctly using the FormBuilder. My Solution will focus on the Reactivity of your form

Below are the steps I have taken

  1. Remove the binding on [disabled] property https://stackoverflow.com/a/58831653/13680115 Below is a warning in the console thrown if you do include [disabled] property


It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
you. We recommend using this approach to avoid 'changed after checked' errors.

Example:
form = new FormGroup({
first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
last: new FormControl('Drew', Validators.required)
});

  1. Remove the onChange event handler. In its place we will have below in our ngOninit function. We will watch for form valuechanges and react to this to disable the appropriate control

      this.printListControl.valueChanges
      .pipe(
        distinctUntilChanged(),
        tap((controls: any[]) => {
          controls.forEach(({ mail, deliveryMethodId }, index) => {
            const control = this.printListControl.at(index);

            if (mail) {
              control.get("deliveryMethodId").enable({ emitEvent: false });
              control.get("recipients").enable({ emitEvent: false });
            } else {
              // I would not include below two lines for better user experience.
              control
                .get("deliveryMethodId")
                .setValue(null, { emitEvent: false });
              control.get("recipients").setValue(null, { emitEvent: false });

              control.get("deliveryMethodId").disable({ emitEvent: false });
              control.get("recipients").disable({ emitEvent: false });
            }

            // console.log(deliveryMethodId);

            control
              .get("recipients")
              .setValidators(this.getRecipientsValidation(deliveryMethodId));
          });
        })
      )
      .subscribe();
  }
  getRecipientsValidation(deliveryMethodId) {
    return +deliveryMethodId === 178
      ? [Validators.pattern(this.emailPattern), Validators.required]
      : +deliveryMethodId === 179
      ? [
          Validators.minLength(10),
            (10),
          Validators.required
        ]
      : [Validators.required];
  }

Now whenever the mail value is changed the deliveryMethodId and recipients control are enabled or disabled

Also we update the validators based on the delivery method selected

  1. Remove the pattern validations from the html. We will use Validators.pattern

We can declare the patterns

emailPattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;

  1. Remove the event for validationErrorOnFocusOut from the template

  2. Since we have removed the template validation, we can employ the use of Validator static classes

    let printList = this.printListArray.map(x => {
      const { deliveryMethodId } = x;
      return this.fb.group({
        id: x.id,
        name: x.name,
        mail: x.mail,
        electronics: x.electronics,
        deliveryMethodId: x.deliveryMethodId,
        recipients: [
          x.recipients,
          {
            validators:
              deliveryMethodId === 178
                ? [Validators.pattern(this.emailPattern), Validators.required]
                : deliveryMethodId === 179
                ? [
                    Validators.minLength(10),
                    Validators.maxLength(10),
                    Validators.required
                  ]
                : [Validators.required],
            updateOn: "blur"
          }
        ]
      });
    });

We are applying validation to each control individally to avoid their effect on other controls

  1. Finally our html will be something like this

<div class="custom-control custom-checkbox"
     *ngFor="let data of exampleForm.get('printList').controls; let j = index" formArrayName="printList">
  <div [formGroupName]="j">
    <table class="table table-print table-borderless">
      <tbody>
      <tr>
        <td scope="row" class="width90">{{data.value.name}}</td>

        <td class="width50">
          <input
            type="checkbox"
            name="mail"
            formControlName="mail"
          />
        </td>
        <td class="width50">
          <input
            type="checkbox"
            name="electronics"
            formControlName="electronics"
          />
        </td>
        <td class="width100">

          <select
            class="custom-select"
            formControlName="deliveryMethodId"
            name="deliveryMethodId"
            tabindex="1" (change)="dropdownSelection(j)"
          >
            <option value=null>Select One </option>
            <option
              *ngFor="let agencyType of DeliveryMethod"
              [value]="agencyType.id"
            >
              {{agencyType.label}}</option
            >
          </select>
        </td>
        <td class="width200">
          <ng-container *ngIf="data.value.deliveryMethodId == 178">
            <input type="text" class="form-control" placeholder="Email" name="Recepient"
                   formControlName="recipients" *ngIf="data.value.deliveryMethodId == 178"
                   [ngClass]="{ 'is-invalid': data.get('recipients').invalid && data.get('recipients').touched }"
                   autocomplete="off">

            <div class='invalid-feedback' *ngIf="data.get('recipients').invalid">
              Please enter valid email
            </div>
          </ng-container>
          <ng-container *ngIf="data.value.deliveryMethodId == 179">
            <input type="text"  prefix="+1 " class="form-control" placeholder="(###) ### - ####"
                   formControlName="recipients" name="recipients" autocomplete="off"
                   *ngIf="data.value.deliveryMethodId == 179"
                   mask=" (000) 000-0000" [showMaskTyped]="false"
                   [ngClass]="{ 'is-invalid' : data.get('recipients').invalid && data.get('recipients').touched }" >

            <div class='invalid-feedback'>
              Please enter valid fax number
            </div>
          </ng-container>
          <ng-container *ngIf="data.value.deliveryMethodId != '178' && data.value.deliveryMethodId != '179'">
            <input type="text" class="form-control" placeholder="Recepient" name="Recepient"
                   [ngClass]="{ 'is-invalid' : data.get('recipients').invalid && data.get('recipients').touched }"
                   formControlName="recipients"
            />
            <div class='invalid-feedback'>
              Field is required
            </div>
          </ng-container>


        </td>
      </tr>
      </tbody>
    </table>
  </div>
</div>

DEMO HERE

这篇关于如何使用angular8在电子邮件和传真的循环项目中显示每一行的验证错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆