Typed Forms in Angular

In Web Development


Typed Forms in Angular - read the full article about Angular Js update, Web Development and from Angular on Qualified.One
alt
Angular
Youtube Blogger
alt

[MUSIC PLAYING] DYLAN HUNN: Hello, Angular community.

My name is Dylan Hunn, and Im a software engineer on the Angular framework team.

Over the last eight months, weve been working on improving Angular forms.

And Im incredibly excited to share this new feature with you today.

Typed forms are part of Angular 14 and are ready today for you to start migrating your application.

Before we jump into the details, lets get some background on reactive forms.

This might already be familiar to anyone who builds or maintains a forms application.

Reactive forms are one way to build forms in Angular.

Compared with template-driven forms, they provide a more explicit data model and state management using RxJS and Observables.

They are not always the right choice.

Template-driven forms are less verbose and better for some use cases.

These new types were going to see today are only for reactive forms.

So thats where well focus.

Lets start with some background on why were making this change and how it benefits most applications that use reactive forms.

Typed forms have long been the most upvoted feature request from the Angular community.

Additionally, this change unlocks a number of future improvements, such as better control state change events, stricter template type checking, and much more.

When designing typed forms, we tried to follow some North stars.

In particular, we had four guiding principles.

First, we want the types to be powerful.

You should be able to confidently modify even the most complex forms, no matter how deeply nested you have form groups or form controls.

Second, we dont want to completely replace forms.

We want to have one unified ecosystem that we move forward together.

Third, we want forms to be as safe as possible, no more surprising anys in your types when you access values or controls.

And fourth, you should be able to gradually migrate at your own pace, even if you have a lot of existing forms code in your application.

Now lets consider an example.

In general, every form corresponds to a schema, or the shape of the data you want to collect.

This is an example schema representing a party.

It has inner objects-- in this case, the address field-- and inner arrays-- in this case, the menu for the party.

Its never necessary to explicitly declare your schema, but its always useful to think about when youre working with a complex form.

By contrast, we do explicitly declare the form model.

And this is the corresponding form for hosting a party.

It accepts inputs for the parties address, for the menu, and for any other form controls you might want.

Previously, interacting with complicated forms models like this one could be hazardous.

For example, this code contains a subtle bug.

The value of place is number and calling a substring on it will crash at runtime.

Now, with typed forms, this bug will be caught at compilation time right in your editor.

These new types permeate the API.

Youll benefit from them when accessing form values, getting deeply nested controls, subscribing to Observables, and so much more at virtually any point you interact with the forms API surface.

This will give you much improved safety, preventing both simple typos and more complex bugs.

The types also allow for robust autocompletion right in your editor.

In the party form example, when accessing the forms value, the IDE suggests every known child of the form.

This helps you navigate even the most complex forms with confidence.

Although this is a big change, its 100% backwards compatible with all of your existing forms code.

When you update to Angular 14, your forms will be automatically opted out of the new types.

Then, when youre ready, you can turn them on one control at a time and incrementally migrate at your own pace.

Now that youve got the basics, lets explore the types in action.

So a moment ago, we saw a schema for building a party.

Now lets have a look at some actual code corresponding to the form for this party.

So lets jump into the template and well add a new button corresponding to hosting a party.

And we will call the partyInSF convenience function.

Now well jump into the corresponding component and well add the convenience function for throwing a party.

We will access this.party from the enclosing component.

This corresponds to the form group for all the partys data.

And we will call setValue on this form group in order to give it a new value.

However, notice that weve actually forgotten the house number.

TypeScript will warn us that we are missing a key here because it expects when we call a set value, all of the keys in the group to be present.

So lets go ahead and add it.

And notice that as I type, the new TypeScript types also power autocompletion.

However, I still have an error here.

The type system doesnt just check for missing properties.

It also just checks for all of the names and all of the types in the object.

So here in particular, whereas I currently have a number key, I should have a house key.

Another option would have been to use patch value instead.

This still protects us against serious typing errors but relaxes the constraint that requires us to have all of the keys present.

In particular, we can just have the straight key.

Now lets consider another case.

Lets say that a neighbor made a noise complaint and we want to figure out which neighbor it was.

So we can add a new method on our component here and we can use the get method.

The get method accepts a string and will automatically tokenize each field in the string, allowing us to access inner controls.

And notice that the type is correctly computed.

In this case, we actually have an error again.

Thats because were trying to do arithmetic with a string key.

And this error tells us we should be using the house key, instead which is numeric.

Now that youve observed the new types up close, lets dive into the nitty-gritty design details.

So consider the form group we saw a moment ago for an address.

What should be the type of address.controls in this example? And on the other hand, what should be the type of address.value? When working with typed forms, its important to know about the difference between the types of values versus the types of controls.

As we saw earlier with the party example, the value is the shape of your data.

Here, for instance, the street field has type string.

On the other hand, you can also access controls.

Here, the street field is a form control, which has a string inside of it.

Typed forms use control types heavily.

Although you rarely need to specify an explicit type, if you do, you should always use the control type.

Another interesting topic is resetting controls.

Lets consider the simplest possible form, just a single control.

When we first consider this control, we see it contains a string.

So we might expect the type to be form control of string.

However, theres a tricky detail.

When youre working with a form control, you can call reset at any time.

And when that happens, the controls value will immediately reset to null.

This means that you cannot always assume the value of a control is a string.

In previous Angular versions, this example would crash at runtime because you cannot call a substring on a null value.

Angular 14 now protects you from these kinds of errors, because the type of the dog control in this example is string or null.

Sometimes, though, thats not actually the behavior you want.

In fact, many existing forms of applications do not rely on the existing nullability of the controls.

In Angular 14, form controls have a brand new option called nonNullable.

Instead of resetting to null, the control will reset to its initial value.

As you might expect, this also removes null from the controls type.

In this example, weve gotten rid of the nulls entirely.

And now calling substring is totally safe.

A related area involves disabled controls and the effect that they have on a forms value.

With Angular forms, disabled controls are not included in the forms value.

This is similar to how native HTML forms behave when their controls are disabled.

However, this has an impact on the type of your form.

When you call dot value, any key in the form group might have been disabled.

As a result, the type knows that each key is optional.

And when you use this value, the type system enforces you handle the possibility that each key might be undefined.

In this example, when using cat.value, all of the fields inside the cat form group are optional, because they might have been disabled.

That, however, is not the only case in which we might have optional keys in our form.

Sometimes you want to be able to freely remove keys from the form.

For example, here we call removeControl on the name name.

With typed forms, we can now explicitly specify which keys are optional versus which are required.

This allows the type system to enforce that we safely handle controls that might be missing.

For form groups that are entirely dynamic, where you want to add or remove many controls, weve also introduced a brand new companion type called FormRecord.

The typing improvements here are wide and deep, and theres so much more to be excited about.

You can read about them in depth in the new typed forms guide available today on angular.io and linked down below in the description.

We are so excited about Angular 14 and the future of typed forms.

We hope that youre as excited as we are, both for this project and for the future of the forms package as a whole.

Please like and subscribe, and thank you for watching.

See you next time.

[MUSIC PLAYING]

Angular: Typed Forms in Angular - Web Development