6
votes

I have an input field that is required only if another value is set. The other value is from a select. Note, my actual form is much more complicated but here is an example showing the parts that are pertinent to this question:

the template:

<form name="createPaymentForm" (ngSubmit)="f.form.valid && createPayment()" #f="ngForm" novalidate>

  <select name="orderNumberType" #orderNumberType="ngModel" 
    [(ngModel)]="payment.orderNumberType">
    <option [ngValue]="undefined" disabled>Select</option>
    <option *ngFor="let opt of paymentIdOptions" [value]="opt.id">{{opt.label}}</option>
  </select>

  <div [ngClass]="{ 'has-error': f.submitted && !orderNumber.valid }">
    <input type="text" name="orderNumber"
      [(ngModel)]="payment.orderNumber" #orderNumber="ngModel">
  </div>

</form>

the component:

import { Component, OnInit } from '@angular/core';
import { PaymentsService } from '../../../services/payments.service';
import { Payment } from '../../../models';

@Component({
  selector: 'app-new-payment',
  templateUrl: './new-payment.component.html',
  styleUrls: ['./new-payment.component.scss']
})
export class NewPaymentComponent implements OnInit {
  paymentIdOptions: any = [];
  payment: Payment = {};

  constructor( private paymentsService: PaymentsService ) { }

  ngOnInit() {
    this.paymentsService.getOrderNumberTypes().subscribe(orderNumberTypes => {
      this.paymentIdOptions = orderNumberTypes;
    });
  }

  createPayment() {
    console.log(this.payment);
    //do something...
  }
}

My goal is to only require the orderNumber if the orderNumberType is set to any value other than 'undefined'. What is the easiest way to implement this?

(Note, Angular 5)

1
I would say that the easiest way is to use reactive forms instead since the ability to add/remove validation at runtime is one of its benefits. Baring that, however, you could add two input boxes each with an ngIf and only show the one with the required attribute if the other value is set. - DeborahK
Hmm, that sounds like it might work (the two boxes with the ngif) but for some reason it feels wrong to me. And sure i could use reactive forms, but I just spent the last few days trying to wrap my head around template driven forms. I'm hoping that template driven forms can have all the same functionality as reactive ones otherwise why would the angular people even bother to offer you an incomplete solution? - Dallas Caley
Template driven is for simple and easy ... the kind of forms that just need straight-forward validation. Reactive forms is for anything that goes beyond the straight-forward. And no ... they are not feature compatible. Otherwise why would they offer two approaches. LOL. :-) - DeborahK
No i don't, not sure what pluralsight is but i have a very difficult time learning from videos (if that is what it is) and tutorials are almost always missing some critical information in my experience. If i can't find an O'Reilly book on the subject then i'd just assume learn from trial and error. - Dallas Caley
@Dallas Caley [required] only need a boolean so give [required]="payment.orderNumberType" if your ids can not be (undefined, null, 0, false or empty string). If you only need to check if undefined [required]="payment.orderNumberType === undefined". - Gilsdav

1 Answers

13
votes

It can be done using required Angular directive like [required]="payment.orderNumberType" (here he check if payment.orderNumberType is undefined, null, 0, false or empty string). This is a shorthand for [attr.required]="payment.orderNumberType ? true : undefined".

You have problem with [ngClass]="{ 'has-error': f.submitted && !orderNumber.valid }" because valid will be set during "ngAfterViewChecked" so Angular don't want to make the job again. Replacing it by [class.has-error]="f.submitted && !orderNumber.valid" will not make it cry anymore.