Loading video player...
Hey there, Angular folks. It's Brian
back again with another signal forms
example. I've made a few tutorials on
signal forms now and I've seen the
comments. Some of you said the old
reactive forms way is just as good or
you just still like it better. And I get
it. Maybe the benefit hasn't been
obvious. So today I'm going to show you
a real world form, the kind that gets
messy fast, and we're going to rebuild
it using signal forms. By the end of
this video, hopefully you'll see the
advantage, not just hear me say it. All
right, let me show you what this form
does real quick before we look at any
code. When I switch this account type to
business, we automatically get a company
name field added. This is what we call
conditional form structure. Super
common, but can get super messy.
Then we have this password field. Now
check out the password strength meter.
The stronger the password becomes, the
more this fills.
The form also knows when it should not
submit. We can't submit yet because it's
still not in a valid state. Let's add a
company name.
And now when we type in an email, if
it's not valid, we get an error message.
Then once it's valid, the error message
goes away. Our form is now valid and the
button activates.
So this is a pretty dynamic form and it
works well. But the way we currently
have this built uses reactive forms. And
to get all of this behavior working, the
code gets a little wild. Let's take a
look at what it takes to make all of
that actually work. First, let's open
our form component TypeScript.
Okay, here we're injecting the
nonnullable form builder from the
reactive forms module. Then we have a
set of variables used to track various
states in this component.
And then below this we have our form
structure created as a form group using
the form builder. We have a control for
the account type that's required.
We have a control for the company name
that's not required initially.
We have a control for the email that is
both required and then uses an email
validator to check for the proper
format.
Then we have a password control that is
required and then has a minlength
validator as well requiring it to be at
least eight characters long. So that's
how we initialize our form. But after
this is where things get spicy.
In order to pull off all of the custom
logic that this form has, we now have
several observable subscriptions for
different aspects of this form. First,
we listen to changes in the account type
to decide whether the company name
should be required. And if not, we clear
validators, reset the value, and
remember to call update value and
validity so the form knows about it.
Then we subscribe again to compute
password strength and update whether the
form can submit. And then another
subscription to track the overall form
validity. At this point, we are no
longer just using the form. We're
babysitting it. We're keeping all of
this state in sync manually.
Then we have a couple of helper methods.
One to determine if we can submit.
Then another to check the strength of
the password.
And finally, we have our empty submit
function that we're not currently doing
anything with.
Okay, so that's the TypeScript.
Now, let's look at the template.
To start here at the top, we're wiring
up our form with the form group
directive on the form element that wraps
all of our fields.
Then to wire up our form controls, we're
using the form control name directive
and then the name of the control within
the form group. Then here we can see
that we have a condition for when we do
have a business account which controls
the visibility of the company name
field.
Below this we have the email field where
we also have a condition based on the
touched and invalid status of the
control that determines whether to show
the email validation message.
Then we have our password field where we
also have our password strength meter.
And below all of this we have our submit
button which is disabled when our cans
submit property is false.
This is all fine and dandy. It all works
and has worked well in the past. The
complicated part isn't here in the
template. It's everything we had to
write to support it. Let's redo this
using signal forms and watch how much of
this code disappears.
Signal forms is a new experimental forms
API in Angular that models forms using
signals instead of form groups and form
controls. It's not production ready yet,
so don't go replacing your company's
checkout flow tomorrow, but it's far
enough along to understand the direction
Angular is heading. And the direction is
less wiring, less bookkeeping, more
direct state. Let's convert this. Let's
switch back over to our TypeScript.
Okay, let's start by removing this form
builder and destroy ref. We won't need
these anymore.
We can also remove the entire form group
now too.
And along with this, we can remove all
of the observable subscriptions and even
the oninit method.
This means we can also remove the oninit
interface
and we can also remove the reactive
forms module import
and then we can remove all unused
imports from the top now as well.
Okay, that's all we're going to remove.
Now the first thing we need to do is
update our account form interface.
Instead of form controls, these will
just be the account type for the account
type control and strings for everything
else. Okay. Now, with reactive forms, we
use the form builder and groups and
controls. But with signal forms, we use
a signal to track the form state. So,
let's create a new signal called form
model and type it with our account form
interface.
Okay. Then we can initialize each of the
properties in this object. So for our
account type, we'll make it personal.
And then for all other fields, we'll
initialize them as an empty string.
Okay. So that's the signal to store our
form state. Now in order to make this
into a form when using signal forms, we
need to create another property where we
use the new form function to wrap this
form state signal. This function creates
what's known as a field tree, but uses
our signal as the source of truth for
the values of our form. To add
validation, we need to pass in some
options.
First, we'll use the new required method
to make our account type field required.
Then, we'll use the required method
again to make our email field required.
Next, we'll use the new email function
to make sure our email is in the proper
format. Then, we'll use the required
method again to make our password field
required. Then, we'll use the min length
function on our password field to set
the min length to eight characters
again. Okay, the last thing we need to
do in our form is make the company name
required when our account type equals
business. With reactive forms, we used
to listen to the value change of the
account type control and then add or
remove the validators and update the
validation state. Well, this gets more
simplistic with signal forms. We can use
the apply when value method to
conditionally apply validation to our
company name control.
So first we check if our account type is
business and if it is we'll use the
required method to set company name
required.
This one function here replaces the
entire account type subscription from
earlier. No updating validators, no
resetting, just describe the rule once.
Okay, so that's our form. Now we need to
update the rest of these properties as
well.
We'll switch the is business property to
a computed signal where we can use the
account type control value since it's a
signal to check if its value is
business.
This property now deres itself. We never
set it manually. This is one of the main
benefits of using signal forms. They are
now signals. So we can do things like
use computed signals or linked signals
or even effects if we need to along with
form controls.
Okay. Now for our password strength
field, we will also convert this to a
computed signal. And here we will
actually copy the guts of the score
method and then we can remove that
method. Instead we'll use this in our
computed signal but we'll use the
password control value as a signal. Now,
okay. Now we will update the cans submit
property to also be a computed signal.
This signal will update based on our
form signal validity and also whether
the password strength value is greater
than or equal to three. Okay. Now we can
remove the old update cans submit method
since it's not needed anymore.
Now, the last thing we need to do here
is we're going to use the new field
directive from the signal forms API in
the template.
So, we need to add this to our component
imports array.
Okay, that should be everything we need
here. I'm hoping if you didn't see the
overall benefit and gains before that,
you see them clearly now. This is quite
a bit less code than it was before and
it integrates seamlessly with Angular's
new reactivity model signals. Okay, now
it's time to switch over and update the
template. Now, the changes here will not
be near as significant as they were in
the TypeScript, but we'll go through
them step by step. First up, we can
remove the form group directive that was
bound to our old form property. Now on
every input that uses the old form
control name directive, we need to
update these to all use the new field
directive and then access the control
off of our new form property. Okay, now
we need to update the is business
condition to use the signal.
We also need to update the email
validation message logic to use signals
now too.
And we also need to update the password
field to use the field directive. And
then we need to switch the password
strength property to a signal 2. Then
all we need to do is update the disabled
binding on our submit button. So the
situation here in the template is not
really all that different. It's not like
a great reduction of code or anything.
It's just converted over to signals and
the new syntax. Overall, not much of a
change here, but this is how you do it
with signal forms.
Okay, this should be everything we need
to change. So, let's go ahead and save
and try this out. And what we should see
is the same UI, same behavior, just
using signals now. All right, let's
click to switch the type. Nice. This
still works. It now shows the company
name field just like it should. All
right, let's try the password. And that
still works, too. Great.
And we can see that the create account
button is still disabled.
Let's add a company name.
Then let's try our email validation.
Nice, that still works. And then once
it's valid, the form becomes valid and
the button is enabled.
So the code went from listen check
update sync track remember to describe
the state the UI follows it. So the form
didn't change the work did. With
reactive forms we had to wire everything
together. Subscribe here toggle
validators there. Track UI state
manually. With signal forms we just
describe the state once and the UI
follows automatically.
Same behavior, less code, clearer logic,
and as your forms get more complex, that
benefit only gets bigger. If you liked
this, like the video and subscribe to
the channel. It really helps more
Angular developers discover these
tutorials. And hey, if you want to show
some Angular pride, check out the Shield
Works United by Craft Gear linked below.
They're for the ones who code like it's
a trade, just like you.
Thanks for watching and I'll see you in
the next one.
If you’ve ever wondered whether Signal Forms are actually better than Reactive Forms, this is the example that makes it obvious (hopefully). 👕 Built for Angular builders. Get some Shieldworks “United by Craft” gear → https://shop.briantree.se In this video, we take a real-world Angular form with conditional fields, validation rules, and derived UI state, and rebuild it using the new Signal Forms API. If you’ve wondered whether Signal Forms are actually an improvement over Reactive Forms, this example makes the difference clear. You'll see how much code disappears once we switch from manually syncing form state to letting the state derive itself through Signals. ------------------------------------------------------------------------------ 🔔 Subscribe for more Angular tutorials & tips → [🔗 https://www.youtube.com/c/briantreese?sub_confirmation=1] 👍 Like this video if you found it helpful, it really helps support the channel! ------------------------------------------------------------------------------ 🔗 Demo Links: - Before (https://stackblitz.com/edit/stackblitz-starters-zfhhuenu?file=src%2Fform%2Fform.component.ts) - After (https://stackblitz.com/edit/stackblitz-starters-gx4z9aho?file=src%2Fform%2Fform.component.ts) ------------------------------------------------------------------------------ 📚 Additional Resources: - Angular Signal Forms GitHub (Experimental): https://github.com/angular/angular/tree/main/packages/forms/signals - Angular FormBuilder Docs: https://angular.dev/api/forms/FormBuilder - My course "Angular: Styling Applications": https://www.pluralsight.com/courses/angular-styling-applications - My course "Angular in Practice: Zoneless Change Detection": https://app.pluralsight.com/library/courses/angular-practice-zoneless-change-detection - Get a Pluralsight FREE TRIAL HERE!: https://www.jdoqocy.com/click-101557355-17135603 ------------------------------------------------------------------------------ 📖 Chapters: 0:00 - Introduction 0:35 - What This Form Needs to Do 1:43 - How This Was Built With Reactive Forms 3:57 - The Reactive Forms Template Setup 5:08 - What Signal Forms Is (and Isn't) 5:38 - Rewriting the Form Using Signal Forms 6:29 - Defining the Form Model as a Signal 7:03 - Creating the Signal-Based Form Structure 8:57 - Deriving UI State with Computed Signals 10:50 - Updating the Template to Use the Field Directive 12:09 - Side-by-Side Behavior Check (Reactive vs Signal) 13:07 - Why This Matters (The Real Benefit) ------------------------------------------------------------------------------ 🧰 About the Tools Used This video demonstrates Angular’s experimental Signal Forms API, which replaces FormGroup and FormControl objects with signal-based state and derived computations. Signal Forms is still experimental and not recommended for production, but it shows the direction Angular is moving, toward simpler form logic, reduced subscriptions, and more maintainable UI state. ------------------------------------------------------------------------------ #angular #angularsignals #signalforms #reactiveforms #webdevelopment #frontend #typescript #angular21 #angulardeveloper #codebetter #cleancode