Back to the homepage
Angular

Template Driven Forms and Reactive Forms

Which one to choose?

Reactive forms are great, we can dynamically create new controls, and validate them synchronously or asynchronously in very different ways. All of this can also be achieved with template driven forms, however, this would require more repetitive code.

On the other hand, if we want to add one control, e.g. a checkbox which hides/shows us a certain component, then creating a form, and then adding listeners is an excess of form over content. All you need is a ngModel with the ngModelChange attribute.

Therefore, the solution is to use both. Details of TDF and RF implementation are very well described in the documentation and also on the angular.love blog. In this article, I will focus on the combination of the two. 

Template Driven Forms

I have worked with Angular since its first versions ( Angular 1.3 to be precise), so Template Driven Forms were the obvious approach for me when I switched to Angular 2. Well implemented, they work great on projects. 

At this point, I should explain what “well implemented” actually means. Imagine you want to add a form in app.component.html:

This isn’t a good implementation. What if we wanted to add several similar forms? A lot of duplicated code will be difficult to change in the future.

It’s much better to make a component out of it. 

Let’s create the MyForms module with the input-text component in it (this is a simplification, therefore in a real project I would advise you to first create a library module, and then the form module). 

 

 

 

 

 

 

 

 

 

We can add this component to the export (at the moment we only have one, but there will be more in the future). 

Now we try to use it in the app.component (remember to import MyModule).

I also added the name attribute, which will be useful later (when it will be embedded in the form). 

Now you should only see the caption: input-text works!

That’s fine because after all, our component isn’t ready yet. 

Let’s start with TS:

Let’s add the provider and the necessary ControlValueAccessor implementation.

Plus the label and name fields.

And HTML:

It now works perfectly and we can create new fields very easily.

If we want to change the appearance or expand it with new opportunities in the future, the changes made in one place will have an overall impact.

Reactive Forms

The advantage of reactive forms is the possibility of creating dynamic forms in a TS file. If you use Reactive Forms together with inputs:

this is not the best approach. A form generator is definitely worth having. You can write it yourself or use the brilliant ngx-formly library.

We install and add the library according to https://formly.dev/guide/getting-started.

Important! We only need FormlyModule without FormlyBootstrapModule

We create a new form-input-text component (our control which is based on input-text however, will be used in the form) and a second form-field (a wrapper for all our components, we only have one input-text at the moment, but in the future, it will probably be input-select, input-converter etc. Thanks to the wrapper, we don’t have to worry about styles such as margins or displaying validation notifications).

We import everything to MyForrms as a root. 

We register our wrapper and our control in the root. We want to use the control as an “input” and we want to use our form-field wrapper on it.

Now we can deal with the input and wrapper code.

Wrapper HTML code:

So far it’s very simple, there is one class only, and indicated where to render the controls using the reference #fieldComponent. In the future, we will add e.g. error messages here. 

We can get rid of <div class = “form-input”> from input-text.component, the class will be in our wrapper.At the moment the TS file only extends the FieldWrapper class.

Similarly does the TS file for FormInputText.

And in its HTML file we add:

If you’re using newer versions of Angular, you have to change strictTemplates to false in tsconfig.json.

Everything is ready now. We only need to add FormlyModule to the export in MyForms.

After adding it, we can start creating our first control and enter it into the app.component.

The library allows you to really do many things. The example above is very primitive. Key – the value will be put under this key, type is the control which will be displayed, and in templateOptions we transfer the label and various attributes.

Now we add to HTML:

These are reactive forms, so the model is optional of course.

Where is the advantage? 

Certainly, the combination of Template Driven Forms and Reactive Forms isn’t dedicated to small applications. The biggest benefit we have is when most of our forms are in Reactive Forms, but sometimes we need to add a control. For example, we want to add a switch which will reveal a new component to us. In the case of taking only the Reactive Forms approach, we would have to define the form, then spot its changes and remember to unsubscribe. In the case of Template Driven, the component just needs to be pasted, ngModelChange set and everything should work.

What’s next? 

Our wrapper component isn’t just for HTML. Our module can certainly be improved by validation, with the result that an incorrect value will be displayed as an error. This is a topic for the next article :).

Link to the GitHub code: https://github.com/rograf/angular-forms-sample.

About the author

Rafal Rogulski

I've been working on the frontend since angular 1.3, the backend in node.js appealed to me with the advent of NestJS. In my free time I like to experiment with new approaches to writing code. Good code for me must meet three characteristics: 1. Work without errors, 2. Be as simple as possible, 3. Be easy to change for new different requirements

Do you want to create articles for our blog together with us? Join us and create valuable content for Angular fans with Angular.love!

Leave a Reply

Your email address will not be published. Required fields are marked *