Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 271b64b

Browse files
committed
docs(forms): clarify NgControlName directive and NgForm
1 parent 1c6594b commit 271b64b

File tree

1 file changed

+57
-50
lines changed

1 file changed

+57
-50
lines changed

public/docs/ts/latest/guide/forms.jade

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ include ../_util-fns
1717

1818
We will build a simple form from scratch, one step at a time. Along the way we'll learn
1919

20-
- How to build an Angular form with a component and template
20+
- to build an Angular form with a component and template
2121

22-
- The `ngModel` two-way data binding syntax for reading and writing values to input controls
22+
- two-way data binding with `[(ngModel)]` syntax for reading and writing values to input controls
2323

24-
- The `ngControl` directive to track the change state and validity of form controls
24+
- using `ngControl` to track the change state and validity of form controls
2525

26-
- The special CSS classes that `ngControl` adds to form controls and how we can use them to provide strong visual feedback
26+
- the special CSS classes that `ngControl` adds to form controls and how we can use them to provide strong visual feedback
2727

28-
- How to display validation errors to users and enable/disable form controls
28+
- displaying validation errors to users and enable/disable form controls
2929

30-
- How to share information across controls with template local variables
30+
- sharing information among controls with template local variables
3131

3232
[Live Example](/resources/live-examples/forms/ts/plnkr.html)
3333
.l-main-section
@@ -75,7 +75,7 @@ figure.image-display
7575
1. Create the `Hero` model class
7676
1. Create the component that controls the form
7777
1. Create a template with the initial form layout
78-
1. Add the **ngModel** directive to each form input control
78+
1. Bind data properties to each form input control with the `ngModel` two-way data binding syntax
7979
1. Add the **ngControl** directive to each form input control
8080
1. Add custom CSS to provide visual feedback
8181
1. Show and hide validation error messages
@@ -240,7 +240,7 @@ ol
240240
<a id="ngModel"></a>
241241
.l-main-section
242242
:marked
243-
## Two-way data binding with ***ngModel**
243+
## Two-way data binding with **ngModel**
244244
Running the app right now would be disappointing.
245245

246246
figure.image-display
@@ -255,7 +255,7 @@ figure.image-display
255255
Now we need to display, listen, and extract at the same time.
256256

257257
We could use those techniques again in our form.
258-
Instead we'll introduce something new, the `NgModel` directive, that
258+
Instead we'll introduce something new, the `[(ngModel)]` syntax, that
259259
makes binding our form to the model super-easy.
260260

261261
Find the `<input>` tag for the "Name" and update it like this
@@ -349,41 +349,43 @@ figure.image-display
349349
## Track change-state and validity with **ngControl**
350350

351351
A form isn't just about data binding. We'd also like to know the state of the controls on our form.
352-
The `NgControl` directive keeps track of control state for us.
353352

354-
.callout.is-helpful
355-
header NgControl requires Form
356-
:marked
357-
The `NgControl` is one of a family of `NgForm` directives that can only be applied to
358-
a control within a `<form`> tag.
359-
:marked
360-
Our application can ask an `NgControl` if the user touched the control,
353+
By setting `ngControl` we create a directive that can tell if the user touched the control,
361354
if the value changed, or if the value became invalid.
362355

363-
`NgControl` doesn't just track state; it updates the control with special
356+
This directive doesn't just track state; it updates the control with special
364357
Angular CSS classes from the set we listed above.
365358
We can leverage those class names to change the appearance of the
366359
control and make messages appear or disappear.
367360

368361
We'll explore those effects soon. Right now
369-
we should **add `ngControl`to all three form controls**,
362+
we should **add `ngControl` to all three form controls**,
370363
starting with the *Name* input box
371364
+makeExample('forms/ts/app/hero-form.component.html', 'ngControl-1', 'app/hero-form.component.html (excerpt)')(format=".")
372365
:marked
373-
Be sure to assign a unique name to each `ngControl` directive.
366+
We set this particular `ngControl` to "name" which makes sense for our app. Any unique value will do.
374367

375368
.l-sub-section
376369
:marked
377-
Angular registers controls under their `ngControl` names
378-
with the `NgForm`.
379-
We didn't add the `NgForm` directive explicitly but it's here
380-
and we'll talk about it [later in this chapter](#ngForm).
370+
Internally Angular creates `Controls` and registers them under their `ngControl` names
371+
with an `NgForm` directive that Angular attached to the `<form>` tag.
372+
We'll talk about `NgForm` [later in the chapter](#ngForm).
373+
374+
The `ngControl` *attribute* in our template actually maps to the
375+
[NgControlName](../api/common/NgControlName-directive.html) directive.
376+
There is also a `NgControl` *abstract* directive which is *not the same thing*.
377+
We often ignore this technical distinction and refer to `NgControlName` more conveniently (albeit incorrectly) as the *NgControl* directive.
378+
379+
While we're under the hood, we might as well note that the `ngModel` in the
380+
two-way binding syntax is now a property of the the `NgControlName` directive.
381+
The `NgModel` directive is no longer involved. We only need one directive to manage the DOM element
382+
and there is no practical difference in the way either directive handles data binding.
381383

382384
.l-main-section
383385
:marked
384386
## Add Custom CSS for Visual Feedback
385387

386-
`NgControl` doesn't just track state.
388+
The *NgControl* directive doesn't just track state.
387389
It updates the control with three classes that reflect the state.
388390

389391
table
@@ -468,13 +470,19 @@ figure.image-display
468470
'name-with-error-msg',
469471
'app/hero-form.component.html (excerpt)')(format=".")
470472
:marked
471-
When we added the `ngControl` directive, we bound it to the the model's `name` property.
472-
473-
Here we initialize a template local variable (`name`) with the value "ngForm" (`#name="ngForm"`).
474-
Angular recognizes that syntax and re-sets the `name` local template variable to the
475-
`ngControl` directive instance.
476-
In other words, the `name` local template variable becomes a handle on the `ngControl` object
477-
for this input box.
473+
We need a template local variable to access the input box's Angular control from within the template.
474+
Here we created a variable called `name` and gave it the value "ngForm".
475+
.l-sub-section
476+
:marked
477+
Why "ngForm"?
478+
A directive's [exportAs](/docs/ts/latest/api/core/DirectiveMetadata-class.html#!#exportAs) property
479+
tells Angular how to link local variable to the directive.
480+
We set `name` to `ngForm` because the `NgControlName` directive's `exportAs` property happens to be "ngForm".
481+
482+
This seems unintuitive at first until we realize that *all* control directives in the
483+
Angular form family &mdash including `NgForm`, `NgModel`, `NgControlName` and `NgControlGroup` &mdash; *exportAs* "ngForm"
484+
and we only ever apply *one* of these directives to an element tag.
485+
Consistency rules!
478486

479487
Now we can control visibility of the "name" error message by binding properties of the `name` control to the message `<div>` element's `hidden` property.
480488
+makeExample('forms/ts/app/hero-form.component.html',
@@ -492,21 +500,7 @@ figure.image-display
492500
Some folks find that behavior disconcerting. They only want to see the message when the user makes an invalid change.
493501
Hiding the message while the control is "pristine" achieves that goal.
494502
We'll see the significance of this choice when we [add a new hero](#new-hero) to the form.
495-
<a id="ngForm"></a>
496-
.l-sub-section
497-
:marked
498-
### The NgForm directive
499-
We just set a template local variable with the value of an `NgForm` directive.
500-
Why did that work? We didn't add the **[`NgForm`](../api/core/NgForm-class.html) directive** explicitly.
501-
502-
Angular added it surreptiously, wrapping it around the `<form>` element
503503

504-
The `NgForm` directive supplements the `form` element with additional features.
505-
It collects `Controls` (elements identified by an `ngControl` directive)
506-
and monitors their properties including their validity.
507-
It also has its own `valid` property which is true only if every contained
508-
control is valid.
509-
:marked
510504
The Hero *Alter Ego* is optional so we can leave that be.
511505

512506
Hero *Power* selection is required.
@@ -582,9 +576,22 @@ figure.image-display
582576
We slipped in something extra there at the end! We defined a
583577
template local variable, **`#heroForm`**, and initialized it with the value, "ngForm".
584578

585-
The variable `heroForm` is now a handle to the `NgForm` directive that we [discussed earlier](#ngForm)
586-
This time `heroForm` remains a reference to the form as a whole.
579+
The variable `heroForm` is now a reference to the `NgForm` directive that governs the form as a whole.
580+
<a id="ngForm"></a>
581+
.l-sub-section
582+
:marked
583+
### The NgForm directive
584+
What `NgForm` directive? We didn't add an [NgForm](../api/core/NgForm-class.html) directive!
585+
586+
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
587587

588+
The `NgForm` directive supplements the `form` element with additional features.
589+
It holds the controls we created for the elements with `ngControl` attributes
590+
and monitors their properties including their validity.
591+
It also has its own `valid` property which is true only *if every contained
592+
control* is valid.
593+
594+
:marked
588595
Later in the template we bind the button's `disabled` property to the form's over-all validity via
589596
the `heroForm` variable. Here's that bit of markup:
590597
+makeExample('forms/ts/app/hero-form.component.html', 'submit-button')
@@ -658,8 +665,8 @@ figure.image-display
658665
- A form component class with a `Component` decorator.
659666
- The `ngSubmit` directive for handling the form submission.
660667
- Template local variables such as `#heroForm`, `#name`, `#alter-ego` and `#power`.
661-
- The `ngModel` directive for two-way data binding.
662-
- The `ngControl` for validation and form element change tracking.
668+
- The `[(ngModel)]` syntax for two-way data binding.
669+
- The `ngControlName` directive for validation and form element change tracking.
663670
- The local variable’s `valid` property on input controls to check if a control is valid and show/hide error messages.
664671
- Controlling the submit button's enabled state by binding to `NgForm` validity.
665672
- Custom CSS classes that provide visual feedback to users about invalid controls.

0 commit comments

Comments
 (0)