Lesson 0.1 Conceptual Goals
This lesson introduces the conceptual goals of the course.
Main Ideas in this Lesson:
- Addressing the question: "What are HTML forms?"
- What the Angular framework brings to forms
- Template-driven vs. Reactive Forms in Angular
- Introducing Form Models
Transcript for this lesson:
Let's discuss our conceptual goals for this course.
So what are HTML forms?
HTML form provide a standardized way of providing a mechanism for users to provide input on the web platform.
For example, on the web platform, there are standardized ways for users to input text numbers, email color, dates, times, et cetera, that are built into the web platform.
In this way, we see that vanilla HTML, supports for this idea of allowing a user to input advanced data.
If you think about your app in terms of how a user would interact with it, you often think about clicking on links or navigating back and forth via your browser. These are definitely ways by which, users provide input to on the web platform.
In the world of front-end web applications, if you consider any application that you would want to build, I think you’d find nearly every time that you have need for retrieving either text, or numbers, or email, or some kind of data.
To facilitate this, the web ecosystems provides HTML forms as a standardized way of communicating these specific types of data from your users.
The standardization allows for a shared experiences across apps. Even if appearances differ from application to application, users tend to be very intuitive about knowing recognizing the core functionality. I think it’s important to keep that in mind as we build new things, given that often we’re dealing with users that have had decades of exposure to the web platform!
This is where the Angular framework, and specifically Angular Forms come into play.
So what are we getting from the angular framework in terms of dealing with forms?
Well, the angular forms package gives you a very well defined API by which we can control standard HTML form elements.
Rather than going into the weeds and managing event listeners and element references, the Angular Forms API condenses it all down into what we really care about.
We care about value, we care about user errors in input, we care about whether the form has been touched by the user or not, and etcetera.
The angular forms package also provides tools by which we can compose complex and or custom forms.
Composing smaller reusable pieces together into larger reusable pieces can be very powerful and effective in terms of managing complexity of our applications, and is a very exciting part of the Forms API.
The Angular Forms API also provides tools to provide feedback to the user or invalid or unexpected input. Often for gather some advanced input from a user, it's unavoidable that a user could potentially enter in some input that just wouldn’t make sense for the functionality we're trying to provide our user via the form. In those situations, we really want to give a user meaningful feedback, as if to say: “Hey, this, this isn't working! And this is why! And this is how you can fix that!”
So the forms API also provides us a way of managing what defines an error, as well as what an error looks like from a data perspective. Building on this, we can provide appropriate feedback to our users and make their lives better.
And then finally the forms API is also a mechanism for local reactive state management.
Reactive State Management is a more complex topic that we'll get into towards the end of the course. Using the RxJS library and providing an observable stream of value changes and status changes, we can essentially work that stream into our “component machine” of functionality.
In effect, this will make our components much more declarative, and the thing I love most about reactive state management, is you in effect are building a machine that can essentially run and manage itself, as opposed to having to code for any combination of events that could possibly occur.
So how do angular forms work?
There's two main strategies for using Angular forms. The first one is template driven forms.
Now template driven forms are somewhat problematic. They feature two-way binding; using banana-in-a-box syntax on the ngModel directive, the idea is that within your component class you would declare a property and bind it to the given input element.
The idea would be that you would bind the value of that input element to that class property in a way that went two-ways - whenever you programmatically change the value of that property within your component class the DOM would update, and whenever the user is interacting directly with your HTML element to change a value, the bound component class property would update as well.
Two-way binding is problematic in itself, because it confuses the flow of logic in your application. Template-driven forms also make it very difficult to detect when changes actually do occur.
When a change does occur using template driven forms it's very hard to capture that specific event and trigger something off of that event. This is still possible with Template-driven forms, you can use angular lifecycle hooks. For example via the DoCheck lifecycle hook you can put logic to check if any class property has changed, and perform some operation if so.
This can be very difficult to manage this and you end up running these kinds of checks every time changes detection moves at all, which can hurt performance as well as make your code significantly more difficult to follow
The alternative is reactive forms which focuses on one-way binding.
In this strategy, you declare a Form control object inside of your component and bind it to elements using the directives that the Forms API provides. This gives you a very unidirectional one-way flow of data.
So we still get all the the benefits that we saw from template driven forms - you may still set the value of the control object at any time, but now that logic very traceable, and exposes a discrete Observable of changes that the form encounters over time.
The main thing to get from this discussion of the two strategies is not to use template driven due to the problems we discussed and to instead focus on reactive forms.
Given the tradeoffs, it really just doesn't make sense to use a template driven forms.
Let's build up a simple mental model of how reactive forms work.
On the screen we have a diagram of a component. We see our component class as well as our HTML template.
So how do we build a reactive form inside of our component?
We start by creating a component class property that houses a control.
Then in of our template we have a target form element or component that we want to bind this control to.
Using the forms-API-provided-directive, we bind our control to the target element. This keeps our control and our form element in sync.
The mechanism by which we can create this bridge here is called the Control Value Accessor.
For every HTML form element, there is a ControlValueAccessor that the Angular Forms API provides out of the box for easily binding to that element.
We can also create our own ControlValueAccessors for custom components, so that we can use this same pattern and control a custom component via the same mechanism.
So let's look at this mental model in the context of the fundamentals of this course.
Our first section is form models.
Inside of our component class we can create either a FormControl, a FormGroup, or a FormArray.
We will explore in this section how to create each of these different types of controls and how to use the provided directives to bind the controls to the appropriate DOM elements.
In our second section we talk about validation.
When we declare a control, we can also declare validator functions to attach to the control.
These validation functions will return whether or not an error exists as well as logic for the data included in that error, all based on the state of this control in question.
With this we can very declaratively dictate when a control is in an error state and as well as how to manipulate DOM elements to provide proper feedback to our users.
Finally, there's the ControlValueAccessor which serves as the final pieces of the fundamental puzzle.
Looking at our mental model below, the ControlValueAccessor encompasses the white arrow that allows us to very easily bind a control to a DOM element.
In this section of the course, we’ll see what all is required to create our own bridge and how we can effortlessly declare very complex forms with rich functionality, in only a few simple lines of class code and html template.
We’ll also see how this is an excellent way of encapsulating complexity!
So let’s start right into it with our First Section on From Models!