A little trick with Angular forms and directives 🃏

timdeschryver profile image Tim Deschryver Originally published at timdeschryver.dev ・2 min read

Imagine having a form that you want to use at multiple places inside your application. The form will have the same layout but the validation will be different.

In our case, this form is used in a multi-step procedure and in each step of the procedure the form gets more restrictive. Can you keep it DRY? We had this problem and came up with the following solution.

The form

As an example let's take a simple form, we have a person with a name, contact info, and allergies.
In the beginning, only the name is required. Later on, we're going to require the rest of the person's info.

  selector: 'person',
  template: `
    <div [formGroup]="form">
        <input type="text" formControlName="name" />

        <label>Contact info</label>
        <input type="text" formControlName="contactInfo" />

        <input type="text" formControlName="allergies" />

      <strong>{{ form.valid ? 'valid' : 'invalid' }}</strong>
export class PersonComponent {
  form = this.formBuilder.group({
    name: ['', Validators.required],
    contactInfo: [''],
    allergies: [''],

  constructor(private formBuilder: FormBuilder) {}

By default, we make the person's name a required field.

The directive

By using an Angular directive we can inject the component's instance, which allows us to access the form. In our case to alter the form's validation and making more fields required.

  selector: 'person[stage-one]',
export class StageOneDirective {
  constructor(host: PersonComponent) {

To be sure that the directive will have the PersonComponent injected, we have to make the directive specific for the person form. To accomplish this, we can use the component's selector as a prefix and append the directive's name to it, person[stage-one]. By doing this, you can only use the directive if the directive is added as an attribute on the person component.
Because the form on the person component is set to public, we can access the form from within our directive. If we have access to the form, we have access to the form fields and their validators.

We can use the same approach to create a stricter validation.

  selector: 'person[stage-two]',
export class StageTwoDirective {
  constructor(host: PersonComponent) {


To make this small example complete, this is how you would use the person component together with or without a directive in another component.

<!-- Only the name is required -->

<!-- The name and the contactInfo are required -->
<person stage-one></person>

<!-- All fields are required -->
<person stage-two></person>

I find this a clean solution in combination with Control Value Accessors, as discussed in Working with Angular forms in an enterprise environment.

Play around with this example in the following blitz.

Posted on by:

timdeschryver profile

Tim Deschryver


NgRx team member - Writer for AngularInDepth


This is where we write about all things Angular. It's meant to be a place for Angular community and people interested in Angular and the Angular ecosystem.


markdown guide

Great use case, thanks. Apart from this one can keep extending the directive like this so a change in validation requirements, is only required in one place.


That's a great tip, thanks Stephan!


Interesting approach how to handle this kind of problem, thanks for sharing!


Thanks Kristaps! I'm happy you liked it!