12

Using Angular 2 (2.0.0), what is the recommended way to dynamically mark a field as required, using Angular Forms?

In all of their examples, the required attribute is just added like:

<input type="text" class="form-control" id="name" required>

What if the model I'm binding to has an IsRequired property, that will be true/false?

If I use something like:

<input [(ngModel)]="field.Value" type="text" value="{{field.Value}}" [attr.required]="field.IsRequired"/>

That renders on the page like (note the ="true"):

<input type="text" required="true" />

For some reason, Angular doesn't appear to recognize this attribute when it has an actual value (the ="true") so when this field is blank, my form itself still is valid:

<form class="ng-untouched ng-pristine ng-valid">

So it would appear that I must use required and not required="true", but how can I add that attribute in dynamically?

What also doesn't work:

<input type="text" {{ getRequiredAttr(field) }} />

Thought I might be able to have a function that returns my string "required" based on the field, that just gives templating errors.

Is there a way to accomplish this and render only required for my attribute? Or a way to make Angular recognize this attribute when it has a value of true/false?

FWIW - I've verified that I can use *ngIf to write two near-identical <input type='text' /> controls based on my IsRequired property and hardcode one with the required attribute but that seems pretty hacky. Hoping there's a better way!

2 Answers 2

15

Why do you have to make it so complicated when you can simply do this,

[required]="isFieldRequired() ? 'required' : null"
Sign up to request clarification or add additional context in comments.

4 Comments

This is probably fine for basic scenarios, yes. Ultimately though, for more complex validations (with custom validators, etc.), I'd prefer to let reactive forms handle as much of it as possible.
I'm relying on reactive forms to catch the validation, but I don't see the asterisk by the field label unless the 'required' attribute is there (picky I know). So this solution was what I needed.
I don't know why this answer is so upvoted. The question is asking how to mark a form as required using the reactive forms API, which this answer actively does not attempt to actually answer.
When we search for how to dynamically add the 'required' attribute to input we get to this question, and this answer answers our question (not sure about the OP's one). So we upvote.
3

The basic forms stuff is great for simple forms, but when you need more control like what you have here, that is when you need to start using the more advanced form stuff. What that would look like in your case would be something like this.

@Component({
  selector: 'something',
  template: `
  <form #myForm="ngForm">
    <input [(ngModel)]="field.Value" [formContol]="myFieldControl" type="text" [value]="field.Value">
  </form>
  `
})
export class MyComponent{
  public field: any = {Value: 'hello', isRequired: false};
  public myFieldControl: FormControl = new FormControl('', [this.dynamicRequiredValidator.bind(this)]);

  public dynamicRequiredValidator(control: FormControl):{[key: string]: boolean}{
    if(field.IsRequired && !control.value){
      return {required: true};
    }
    return {};
  }
}

Note: You will probably need to import the ReactiveFormsModule into your @NgModule. This comes from @angular/forms as well.

There is also another way you can do this with a directive shown here.

5 Comments

Interesting - I'll give this a shot. Thanks!
I guess it isn't quite there. My <form> still shows ng-valid although my field now is correctly ng-invalid. Do I need to do something special for the form to get updated correctly? I assume this is because the required attribute isn't actually present with your solution?
When using FormControl the attribute won't appear. The validators are passed into the FormControl as the second argument, which is an array of validators. This is the funny [this.dynamicRequiredValidator.bin(this)] part. You're also going to want to make sure that you are using (ngSubmit) on your <form> to trigger the validation. To debug I would recommend a few console.log() in the dynamicRequiredValidator to ensure it's being run, and that it's returning the right result
Oh, wait, you were talking about the form itself... Umm... Have a look at FormBuilder or FormGroup
That's what I'm looking into now. I didn't specify that well enough in my question. Your answer still stands as working for what I asked :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.