简体   繁体   中英

Angular 2 Form Validation Using Validators WIth An Element That Is Dynamically Built Using *ngIf

I have a form and am using Reactive Forms for validation. I can get all the validation to work EXCEPT I have some inputs that are served conditionally that are still keeping the form from validating even when they are not served to the view using *ngIf. How can I say "Validators.required" only if a condition is true. Please see example.

constructor(
    private QRService:QRService,
    fb: FormBuilder
    ){
    this.title = 'My Form';
    this.showDeliveryTypes = false;
    this.complexForm = fb.group({
      'itemnumber' : [null, Validators.required],
      'dateofbirth' : [null, Validators.required],
      'deliverytype' : [null, Validators.required],
      'pickuplocation' : [null, Validators.required], //validates even if these aren't included using *ngIf
      'paymentoptions' : [null, Validators.required] //validates even if these aren't included using *ngIf
   })

};

I only want to validate pickuplocations or paymentoptions if the *ngIf includes them in the form.

<form [formGroup]="complexForm" (ngSubmit)="findScript(complexForm.Form)">
  <h2>Script Number</h2>
  <input type="number" name="script" [(ngModel)]="itemno" (blur)="getScripts(itemno)" [formControl]="complexForm.controls['itemnumber']">
  <h2>Date of birth</h2>
  <input type="date" name="dob" [(ngModel)]="dateofbirth" (blur)="getScripts(scriptno, dateofbirth)" [formControl]="complexForm.controls['dateofbirth']" required>
  <div *ngIf="showDeliveryTypes" name="deliverytypes">
  <h3>Delivery Method</h3>
  <select #select [(ngModel)]="selectedId" (change)="validateDeliveryTypes(select.value)" name="deliveryoptions" [formControl]="complexForm.controls['deliverytype']">
    <option *ngFor="let item of qrData.DeliveryTypes" [value]="item.DeliveryTypeId">{{item.DeliveryTypeName}}</option>

  </select>
  </div>
  <div *ngIf="showPickupLocations" name="pickuptypes">
  <h3>Pickup Locations</h3>  //I don't want to validate these UNLESS the *ngIf is true
  <select #select [(ngModel)]="selectedPickupId" (change)="checkVals(select.value)" name="pickupoptions" [formControl]="complexForm.controls['pickuplocation']">
    <option *ngFor="let item of selectedItem.PickupLocations" [value]="item.PickupLocationId">{{item.PickupLocationName}}</option>

  </select>
  </div>
  <div *ngIf="showPaymentOptions" name="paymentoptions">
  <h3>Payment Types</h3>  //I don't want to validate these UNLESS the *ngIf is true
  <select #select [(ngModel)]="selectedPayment" (change)="checkVals(select.value)" name="selectpaymentoptions" [formControl]="complexForm.controls['paymentoptions']">
    <option *ngFor="let item of selectedItem.PaymentTypes" [value]="item.PaymentTypeId">{{item.PaymentTypeName}}</option>

  </select>
  </div>
  <button (click)="findScript()" type="submit" name="submitbutton" [disabled]="!complexForm.valid">Find Prescription</button>
</form>

I'm still fairly new to Angular2 and can do this easily in Angular 1, but really wanting to move to Angular2 with future development.

One way would be to disable the form field when you are hiding it from the DOM. Disabling the form control, excludes that form field from the form entirely, which is what you want. If you do need to get the value included in your form upon submit, you can use the method getRawValue . But otherwise the form fields will be excluded entirely.

Since your form is pretty complex, I have set up a simple example code and plunker for you, where we disable lastname and remove it from the DOM.

Since not knowing how you toggle the showPickupLocations and showPaymentOptions , I'll just use a button here, which toggles the visibility of lastname. So the form would look like this:

<button (click)="toggle()">Toggle lastname</button>
<form [formGroup]="myForm">
  <label>firstname: </label>
  <input formControlName="firstname"/>
  <div *ngIf="toggl">
     <label>lastname: </label>
     <input formControlName="lastname"/>
  </div>
</form>

And when we toggle lastname visibility in DOM, we also toggle the enabling and disabling of the formfield:

toggle() {
  this.toggl = !this.toggl;
  let control = this.myForm.get('lastname')
  control.enabled ? control.disable() : control.enable()
}

As said, this excludes the field from the form, so validation will not be a problem. In this demo plunker you can see how the toggling removes the lastname field from the form values entirely.

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM