docs(guide): Update Dart forms chapter to alpha.52

closes #471
This commit is contained in:
Kathy Walrath 2015-12-10 12:43:13 -08:00
parent 92f1690b73
commit 8e8963270b
8 changed files with 91 additions and 91 deletions

View File

@ -4,16 +4,16 @@
<!-- #docregion edit-div -->
<div [hidden]="submitted">
<h1>Hero Form</h1>
<!-- #docregion ng-submit -->
<form (ng-submit)="onSubmit()" #hf="form">
<!-- #enddocregion ng-submit -->
<!-- #docregion ngSubmit -->
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<!-- #enddocregion ngSubmit -->
<!-- #enddocregion edit-div -->
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion name-with-error-msg -->
<input type="text" class="form-control" required
[(ng-model)]="model.name"
ng-control="name" #name="form" >
[(ngModel)]="model.name"
ngControl="name" #name="ngForm" >
<div [hidden]="name.valid" class="alert alert-danger">
Name is required
</div>
@ -23,22 +23,22 @@
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo"
ng-control="alterEgo" >
[(ngModel)]="model.alterEgo"
ngControl="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power"
ng-control="power" >
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
[(ngModel)]="model.power"
ngControl="power" >
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #docregion submit-button -->
<button type="submit" class="btn btn-default"
[disabled]="!hf.form.valid">Submit</button>
[disabled]="!heroForm.form.valid">Submit</button>
<!-- #enddocregion submit-button -->
<!-- #docregion edit-div -->
</form>

View File

@ -4,26 +4,26 @@
<form>
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion ng-control-1 -->
<!-- #docregion ngControl-1 -->
<input type="text" class="form-control" required
[(ng-model)]="model.name"
ng-control="name" >
<!-- #enddocregion ng-control-1 -->
[(ngModel)]="model.name"
ngControl="name" >
<!-- #enddocregion ngControl-1 -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo"
ng-control="alterEgo" >
[(ngModel)]="model.alterEgo"
ngControl="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power"
ng-control="power" >
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
[(ngModel)]="model.power"
ngControl="power" >
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>

View File

@ -2,28 +2,28 @@
<div class="container">
<h1>Hero Form</h1>
<form>
<!-- #docregion ng-model-2 -->
<!-- #docregion ngModel-2 -->
{{diagnostic}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required
[(ng-model)]="model.name" >
[(ngModel)]="model.name" >
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo">
[(ngModel)]="model.alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power">
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
[(ngModel)]="model.power">
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion ng-model-2 -->
<!-- #enddocregion ngModel-2 -->
<button type="submit" class="btn btn-default">Submit</button>
</form>

View File

@ -4,11 +4,11 @@
<form>
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion ng-model-1 -->
<!-- #docregion ngModel-1 -->
<input type="text" class="form-control" required
[(ng-model)]="model.name" >
[(ngModel)]="model.name" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ng-model-1 -->
<!-- #enddocregion ngModel-1 -->
</div>
<div class="form-group">
@ -20,7 +20,7 @@
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required>
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion powers -->

View File

@ -4,25 +4,25 @@
<form>
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion ng-model-3 -->
<!-- #docregion ngModel-3 -->
<input type="text" class="form-control" required
[ng-model]="model.name"
(ng-model-change)="model.name = $event" >
[ngModel]="model.name"
(ngModel-change)="model.name = $event" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ng-model-3 -->
<!-- #enddocregion ngModel-3 -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo">
[(ngModel)]="model.alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power">
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
[(ngModel)]="model.power">
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>

View File

@ -4,27 +4,27 @@
<form>
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion ng-control-2 -->
<!-- #docregion ngControl-2 -->
<input type="text" class="form-control" required
[(ng-model)]="model.name"
ng-control="name" #spy >
[(ngModel)]="model.name"
ngControl="name" #spy >
TODO: remove this: {{spy.className}}
<!-- #enddocregion ng-control-2 -->
<!-- #enddocregion ngControl-2 -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo"
ng-control="alterEgo" >
[(ngModel)]="model.alterEgo"
ngControl="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power"
ng-control="power" >
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
[(ngModel)]="model.power"
ngControl="power" >
<option *ngFor="#p of powers" [value]="p">{{p}}</option>
</select>
</div>

View File

@ -3,7 +3,7 @@ name: hero_form
description: Form example
version: 0.0.1
dependencies:
angular2: 2.0.0-alpha.47
angular2: 2.0.0-alpha.52
browser: ^0.10.0
transformers:
- angular2:

View File

@ -20,11 +20,11 @@ include ../../../../_includes/_util-fns
- How to build an Angular form with a component and template
- The `ng-model` two-way data binding syntax for reading and writing values to input controls
- The `ngModel` two-way data binding syntax for reading and writing values to input controls
- The `ng-control` directive to track the change state and validity of form controls
- The `ngControl` directive to track the change state and validity of form controls
- The special CSS classes that `ng-control` adds to form controls and how to use them to provide strong visual feedback
- The special CSS classes that `ngControl` adds to form controls and how to use them to provide strong visual feedback
- How to display validation errors to users and enable/disable form controls
@ -79,11 +79,11 @@ figure.image-display
1. Create the `Hero` model class.
1. Create the component that controls the form.
1. Create a template with the initial form layout.
1. Add the **ng-model** directive to each form input control.
1. Add the **ng-control** directive to each form input control.
1. Add the **ngModel** directive to each form input control.
1. Add the **ngControl** directive to each form input control.
1. Add custom CSS to provide visual feedback.
1. Show and hide validation error messages.
1. Handle form submission with **ng-submit**.
1. Handle form submission with **ngSubmit**.
1. Change the form's display after submission.
:marked
@ -236,7 +236,7 @@ figure.image-display
.l-main-section
:marked
## Add powers with ***ng-for**
## Add powers with ***ngFor**
Our hero must choose one super power from a fixed list of Agency-approved powers.
We maintain that list internally (in `HeroFormComponent`).
@ -255,7 +255,7 @@ figure.image-display
.l-main-section
:marked
## Two-way data binding with ***ng-model**
## Two-way data binding with ***ngModel**
Running the app right now would be disappointing.
figure.image-display
@ -275,7 +275,7 @@ figure.image-display
Find the `<input>` tag for Name and update it like this:
+makeExample('forms/dart/lib/hero_form_component_ngmodel_ngfor.html', 'ng-model-1', 'lib/hero_form_component.html (excerpt)')(format=".")
+makeExample('forms/dart/lib/hero_form_component_ngmodel_ngfor.html', 'ngModel-1', 'lib/hero_form_component.html (excerpt)')(format=".")
.l-sub-section
:marked
@ -284,32 +284,32 @@ figure.image-display
We left ourselves a note to throw it way when we're done.
:marked
Focus on the binding syntax: `[(ng-model)]="..."`.
Focus on the binding syntax: `[(ngModel)]="..."`.
If we ran the app right now and started typing in the Name input box,
adding and deleting characters, we'd see them appearing and disappearing
from the interpolated text.
At some point it might look like this.
figure.image-display
img(src="/resources/images/devguide/forms/ng-model-in-action.png" width="400px" alt="ng-model in action")
img(src="/resources/images/devguide/forms/ng-model-in-action.png" width="400px" alt="ngModel in action")
:marked
The diagnostic is evidence that values really are flowing from the input box to the model and
back again. **That's two-way data binding!**
Let's add similar `[(ng-model)]` bindings to Alter Ego and Hero Power.
Let's add similar `[(ngModel)]` bindings to Alter Ego and Hero Power.
We'll ditch the input box binding message
and add a new binding at the top to the component's `diagnostic` property.
Then we can confirm that two-way data binding works *for the entire Hero model*.
After revision, the core of the form should have three `[(ng-model)]` bindings that
After revision, the core of the form should have three `[(ngModel)]` bindings that
look much like this:
+makeExample('forms/dart/lib/hero_form_component_ngmodel2.html', 'ng-model-2', 'lib/hero_form_component.html (excerpt)')(format=".")
+makeExample('forms/dart/lib/hero_form_component_ngmodel2.html', 'ngModel-2', 'lib/hero_form_component.html (excerpt)')(format=".")
:marked
If we ran the app right now and changed every Hero model property, the form might look like this:
figure.image-display
img(src="images/ng-model-in-action-2.png" width="500px" alt="ng-model in super action")
img(src="images/ng-model-in-action-2.png" width="500px" alt="ngModel in super action")
:marked
The diagnostic near the top of the form
confirms that our changes to the values are reflected in the model.
@ -318,9 +318,9 @@ figure.image-display
.l-sub-section
h3 Inside [(ng-model)]
h3 Inside [(ngModel)]
:marked
*This section is an optional deep dive into [(ng-model)]. Not interested? Skip ahead!*
*This section is an optional deep dive into [(ngModel)]. Not interested? Skip ahead!*
The punctuation in the binding syntax, <span style="font-family:courier"><b>[()]</b></span>, is a good clue to what's going on.
@ -337,22 +337,22 @@ figure.image-display
In fact, we can break the `NgModel` binding into its two separate modes
as in this rewrite of the Name `<input>` binding:
+makeExample('forms/dart/lib/hero_form_component_ngmodelchange.html', 'ng-model-3')(format=".")
+makeExample('forms/dart/lib/hero_form_component_ngmodelchange.html', 'ngModel-3')(format=".")
:marked
<br>The property binding should feel familiar. The event binding might seem strange.
The name `ng-model-change` specifies an event property of the `NgModel` directive.
The name `ngModel-change` specifies an event property of the `NgModel` directive.
When Angular sees a binding target in the form <span style="font-family:courier">[(abc)]</span>,
it expects the `abc` directive to have an `abc` input property and an `abc-change` output property.
The other oddity is the template expression, `model.name = $event`.
We're used to seeing an `$event` object coming from a DOM event.
The `ng-model-change` property doesn't produce a DOM event; it's an Angular `EventEmitter`
The `ngModel-change` property doesn't produce a DOM event; it's an Angular `EventEmitter`
property that returns the input box value when it fires—which is precisely what
we should assign to the model's `name` property.
Nice to know but is it practical? `[(ng-model)]` is usually what we want, but
Nice to know but is it practical? `[(ngModel)]` is usually what we want, but
we might split the binding when the event handling has to do something special
such as debounce or throttle the keystrokes.
@ -364,7 +364,7 @@ figure.image-display
.l-main-section
:marked
## Track change-state and validity with **ng-control**
## Track change-state and validity with **ngControl**
A form isn't just about data binding. We'd also like to know the state of the controls on our form.
The `NgControl` directive keeps track of control state for us.
@ -384,15 +384,15 @@ figure.image-display
control and make messages appear or disappear.
We'll explore those effects soon. Right now
let's **add `ng-control`to all three form controls**,
let's **add `ngControl`to all three form controls**,
starting with the Name input box.
+makeExample('forms/dart/lib/hero_form_component_ngcontrol.html', 'ng-control-1', 'lib/hero_form_component.html (excerpt)')(format=".")
+makeExample('forms/dart/lib/hero_form_component_ngcontrol.html', 'ngControl-1', 'lib/hero_form_component.html (excerpt)')(format=".")
:marked
Be sure to assign a unique name to each `ng-control` directive.
Be sure to assign a unique name to each `ngControl` directive.
.l-sub-section
:marked
Angular registers controls under their `ng-control` names
Angular registers controls under their `ngControl` names
with the `NgForm` directive.
We didn't add the `NgForm` directive explicitly but it's here;
we'll talk about it [later in this chapter](#ng-form).
@ -429,7 +429,7 @@ figure.image-display
named **spy**
to the Name `<input>` tag and use the spy to display those classes.
+makeExample('forms/dart/lib/hero_form_component_spy.html', 'ng-control-2')(format=".")
+makeExample('forms/dart/lib/hero_form_component_spy.html', 'ngControl-2')(format=".")
:marked
Now run the app, and look at the Name input box.
@ -442,8 +442,8 @@ figure.image-display
The classes are displayed as follows:
1. `form-control ng-untouched ng-pristine ng-valid` (initial state)
1. `form-control ng-pristine ng-valid ng-touched` (after clicking)
1. `form-control ng-untouched ng-valid ng-pristine` (initial state)
1. `form-control ng-valid ng-pristine ng-touched` (after clicking)
1. `form-control ng-valid ng-touched ng-dirty` (after changing)
1. `form-control ng-touched ng-dirty ng-invalid` (after erasing)
@ -498,11 +498,11 @@ figure.image-display
+makeExample('forms/dart/lib/hero_form_component.html', 'name-with-error-msg', 'lib/hero_form_component.html (excerpt)', stylePattern)(format=".")
:marked
We initialized the template local variable with the string "form"
(`#name="form"`).
We initialized the template local variable with the string "ngForm"
(`#name="ngForm"`).
Angular recognizes that syntax and sets the `name` variable
to the `Control` object identified by the `ng-control` directive that,
to the `Control` object identified by the `ngControl` directive that,
not coincidentally, we called "name".
We bind the `Control` object's `valid` property to the element's `hidden` property.
@ -513,14 +513,14 @@ figure.image-display
h3 The NgForm directive
:marked
Recall from the previous section that `ng-control` registered this input box with the
Recall from the previous section that `ngControl` registered this input box with the
`NgForm` directive as "name".
We didn't add the `NgForm`<!-- TODO: link to (../api/core/NgForm-class.html) --> directive explicitly.
Angular added it surreptitiously, wrapping it around the `<form>` element.
The `NgForm` directive supplements the `<form>` element with additional features.
It collects controls (elements identified by an `ng-control` directive)
It collects controls (elements identified by an `ngControl` directive)
and monitors their properties including their validity.
It has its own `valid` property, which is true only if every contained
control is valid.
@ -539,7 +539,7 @@ figure.image-display
.l-main-section
:marked
## Submit the form with **ng-submit**
## Submit the form with **ngSubmit**
The user should be able to submit this form after filling it in.
The Submit button at the bottom of the form
does nothing on its own, but it will
@ -548,18 +548,18 @@ figure.image-display
A "form submit" is meaningless at the moment. To make it meaningful,
we'll update the `<form>` tag with another Angular directive, `NgSubmit`,
and bind it to the `HeroFormComponent.onSubmit()` method:
+makeExample('forms/dart/lib/hero_form_component.html', 'ng-submit')(format=".")
+makeExample('forms/dart/lib/hero_form_component.html', 'ngSubmit')(format=".")
:marked
We slipped in something extra there at the end! We defined a
template local variable, **`#hf`**, and initialized it with the value "form".
template local variable, **`#heroForm`**, and initialized it with the value "ngForm".
The variable `hf` is now a handle to the `NgForm` as we [discussed earlier](#ng-form)
with respect to `ng-control`, although this time we have a reference to the form
The variable `heroForm` is now a handle to the `NgForm` as we [discussed earlier](#ng-form)
with respect to `ngControl`, although this time we have a reference to the form
rather than a control.
We'll bind the form's overall validity via
the `hf` variable to the button's `disabled` property
the `heroForm` variable to the button's `disabled` property
using an event binding. Here's the code:
+makeExample('forms/dart/lib/hero_form_component.html', 'submit-button')(format=".")
:marked
@ -631,10 +631,10 @@ figure.image-display
- An Angular HTML form template.
- A form component class with a `Component` decorator.
- The `ng-submit` directive for handling the form submission.
- Template local variables such as `#hf`, `#name`, `#alter-ego`, and `#power`.
- The `ng-model` directive for two-way data binding.
- The `ng-control` directive for validation and form element change tracking.
- The `ngSubmit` directive for handling the form submission.
- Template local variables such as `#heroForm`, `#name`, `#p`, and `#spy`.
- The `ngModel` directive for two-way data binding.
- The `ngControl` directive for validation and form element change tracking.
- The local variables `valid` property on input controls to check if a control is valid and show/hide error messages.
- Property binding to disable the submit button when the form is invalid.
- Custom CSS classes that provide visual feedback to users about required invalid controls.