238

Suppose we're building an address book application (contrived example) with AngularJS.

We have a form for contacts that has inputs for email and phone number, and we want to require one or the other, but not both: We only want the email input to be required if the phone input is empty or invalid, and vice versa.

Angular has a required directive, but it's not clear from the documentation how to use it in this case. So how can we conditionally require a form field? Write a custom directive?

banana
  • 1,186
  • 4
  • 14
  • 26
Christian Smith
  • 8,089
  • 3
  • 19
  • 18

6 Answers6

473

There's no need to write a custom directive. Angular's documentation is good but not complete. In fact, there is a directive called ngRequired, that takes an Angular expression.

<input type='email'
       name='email'
       ng-model='contact.email' 
       placeholder='your@email.com'
       ng-required='!contact.phone' />

<input type='text'
       ng-model='contact.phone'             
       placeholder='(xxx) xxx-xxxx'
       ng-required='!contact.email' />  

Here's a more complete example: http://jsfiddle.net/uptnx/1/

Christian Smith
  • 8,089
  • 3
  • 19
  • 18
  • 5
    It shouldn't be a problem, right? Just update the conditionals accordingly. If you explain what you need a bit more I (or other person here) will be able to show you :) – Puce Feb 02 '15 at 09:31
  • 1
    As a side note, you can also use a function and do more complex logic there. – Leandro Zubrezki Nov 22 '15 at 12:47
  • 1
    This feature is documented by now: https://docs.angularjs.org/api/ng/directive/ngRequired – bjunix May 09 '16 at 11:42
26

if you want put a input required if other is written:

   <input type='text'
   name='name'
   ng-model='person.name'/>

   <input type='text'
   ng-model='person.lastname'             
   ng-required='person.name' />  

Regards.

David Gonzalez
  • 751
  • 7
  • 6
15

For Angular2

<input type='email' 
    [(ngModel)]='contact.email'
    [required]='!contact.phone' >
laffuste
  • 16,287
  • 8
  • 84
  • 91
  • EDIT: This is throwing a console error "ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked." when I check the radio button I'm applying this on, but it does appear to do the conditional validation. – Eric Soyke Feb 15 '18 at 21:01
  • 4
    Angular2+ isn't tagged on this question. Since it's essentially a different framework, this answer isn't relevant. – isherwood Mar 01 '18 at 15:39
  • 1
    @isherwood you are right. I added it because I ended here while googling for that. I will delete it if it gets downvoted or controversial. – laffuste Aug 09 '18 at 09:39
  • @Iaffuste you could post and reply on a new question for Angular2+ to make it easy for people looking into this. +1 anyway =) – remmargorp Sep 28 '18 at 08:45
14

Simple you can use angular validation like :

 <input type='text'
   name='name'
   ng-model='person.name'
   ng-required='!person.lastname'/>

   <input type='text'
   name='lastname'
   ng-model='person.lastname'             
   ng-required='!person.name' /> 

You can now fill the value in only one text field. Either you can fill name or lastname. In this way you can use conditional required fill in AngularJs.

Bipin Shilpakar
  • 188
  • 2
  • 9
0

In AngularJS (version 1.x), there is a build-in directive ngRequired

<input type='email'
       name='email'
       ng-model='user.email' 
       placeholder='your@email.com'
       ng-required='!user.phone' />

<input type='text'
       ng-model='user.phone'             
       placeholder='(xxx) xxx-xxxx'
       ng-required='!user.email' /> 

In Angular2 or above

<input type='email'
       name='email'
       [(ngModel)]='user.email' 
       placeholder='your@email.com'
       [required]='!user.phone' />

<input type='text'
       [(ngModel)]='user.phone'             
       placeholder='(xxx) xxx-xxxx'
       [required]='!user.email' /> 
Majedur
  • 3,074
  • 1
  • 30
  • 43
0

For Angular 2

<input [(ngModel)]='email' [required]='!phone' />
<input [(ngModel)]='phone' [required]='!email' /> 
Patrick Ferreira
  • 1,983
  • 1
  • 15
  • 31