Dive into Reactive Forms

Sync values between multiple AbstractControl

🦊 Reactive Fox 🚀
Angular In Depth
4 min readMar 25, 2019

--

Today I’m going to show you a simple way to sync values in FormControl, FormGroup, and FormArray.

AngularInDepth is moving away from Medium. More recent articles are hosted on the new platform inDepth.dev. Thanks for being part of indepth movement!

The problem

Let’s assume that we have a form with multiple controls in which we have a list of animals with their names and colors.

What we need here is to sync all animal values, so that a change in one control will be applied to all the others.

To begin with, we can create one FormControl for animal and use it across the entire form:

But if you try to do so, the form won’t work as expected. This is because FormControl, like any other AbstractControl, can have only one parent. Why? Take a look at what happens inside a reactive form:

As we see, when the form initializes, each form control gets a parent. That’s why there will be issues when the value of animal changes. How can we solve the problem then?

In the search of the solution

In order to reuse the control sync code, let’s create a ControlLinker class and implement all the necessary parts:

Note that we indicated T extends AbstractControl in the class definition. This is required to be able to explicitly pass the type of control: FormControl, FormGroup, FormArray. And AbstractControl will be used as the default type.

Now, that we have our ControlLinker class, let’s add the ability to register other AbstractControl and put them into a linked list by implementing the link() and unlink() methods:

Great! Next, when we have a list of controls, we need to detect their changes. This can be achieved by subscribing to control changes:

And here’s what we got. When any control has received a new value, the value will be set in all registered controls. That way no matter which control has been changed, they all will have the same value!

Don’t forget to unsubscribe when removing the control. Let’s do it this way:

That’s it! Now we’re sure that our controls are synced. Let’s try it!

Push the button

ControlLinker is very easy to use. We only need to create an instance, and then pass all controls that we want to sync to it. In our case, we pass all animal controls:

Now, all of our control values are synced.

https://stackblitz.com/edit/animals-with-control-linker

Conclusions

We found an easy way to sync reactive form control values.

We learned a useful pattern that allows simplifying the syncing of forms and their values.

Do not forget that it’s very important to keep the code of your components as declarative as you can. This improves maintainability.

🙀 Oh, and most importantly! Did you know Why you HAVE to unsubscribe from Observable?

You can always reach me via Twitter where I publish a lot of interesting things and can discuss something.

Don’t forget to follow me on Twitter, Medium, and GitHub, 👏Clap Clap 👏 this story, and subscribe to Angular in Depth without takeUntil()!

--

--

🦊 Reactive Fox 🚀
Angular In Depth

⚡️ Making Fast faster 👩‍💻 Lead Software Engineer using @angular & @dotnet 🌱 Google Developer Expert for Angular ✍ Tech Writer for @AngularInDepth 🦊 he/him