docs(forms): add link to Dart sample (#2176)

Contributes to #1598.

Also:
- Trimmed trailing whitespace.
- Fixing user-input (since we don’t need the “Run the” in the link).
This commit is contained in:
Patrice Chalin 2016-08-22 15:41:13 -07:00 committed by Kathy Walrath
parent 9b3614d151
commit fcaf8fa365
4 changed files with 52 additions and 51 deletions

View File

@ -1,6 +1,5 @@
include ../_util-fns include ../_util-fns
<!-- http://plnkr.co/edit/wg154K -->
:marked :marked
Weve all used a form to log in, submit a help request, place an order, book a flight, Weve all used a form to log in, submit a help request, place an order, book a flight,
schedule a meeting, and perform countless other data entry tasks. schedule a meeting, and perform countless other data entry tasks.
@ -30,6 +29,8 @@ include ../_util-fns
- How to share information across controls with template reference variables - How to share information across controls with template reference variables
Run the <live-example></live-example>.
.l-main-section .l-main-section
:marked :marked
## Template-driven forms ## Template-driven forms

View File

@ -6,7 +6,7 @@ include ../_util-fns
In this chapter we learn to bind to those events using the Angular In this chapter we learn to bind to those events using the Angular
event binding syntax. event binding syntax.
<live-example>Run the live example</live-example>. Run the <live-example></live-example>.
:marked :marked
## Binding to user input events ## Binding to user input events

View File

@ -21,15 +21,15 @@ include ../_util-fns
- two-way data bind with `[(ngModel)]` syntax for reading and writing values to input controls - two-way data bind with `[(ngModel)]` syntax for reading and writing values to input controls
- track the change state and validity of form controls using `ngModel` in combination with a form - track the change state and validity of form controls using `ngModel` in combination with a form
- provide strong visual feedback using special CSS classes that track the state of the controls - provide strong visual feedback using special CSS classes that track the state of the controls
- display validation errors to users and enable/disable form controls - display validation errors to users and enable/disable form controls
- use [template reference variables](./template-syntax.html#ref-vars) for sharing information among HTML elements - use [template reference variables](./template-syntax.html#ref-vars) for sharing information among HTML elements
<live-example>Live Example</live-example> Run the <live-example></live-example>.
.l-main-section .l-main-section
:marked :marked
@ -107,13 +107,13 @@ include ../_quickstart_repo
The TypeScript compiler generates a public field for each `public` constructor parameter and The TypeScript compiler generates a public field for each `public` constructor parameter and
assigns the parameters value to that field automatically when we create new heroes. assigns the parameters value to that field automatically when we create new heroes.
The `alterEgo` is optional and the constructor lets us omit it; note the (?) in `alterEgo?`. The `alterEgo` is optional and the constructor lets us omit it; note the (?) in `alterEgo?`.
We can create a new hero like this: We can create a new hero like this:
code-example(format=""). code-example(format="").
let myHero = new Hero(42, 'SkyDog', let myHero = new Hero(42, 'SkyDog',
'Fetch any object at any distance', 'Fetch any object at any distance',
'Leslie Rollover'); 'Leslie Rollover');
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog" console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
:marked :marked
@ -159,7 +159,7 @@ code-example(format="").
write (or read) large stretches of HTML and few editors are much help with files that have a mix of HTML and code. write (or read) large stretches of HTML and few editors are much help with files that have a mix of HTML and code.
We also like short files with a clear and obvious purpose like this one. We also like short files with a clear and obvious purpose like this one.
We made a good choice to put the HTML template elsewhere. We made a good choice to put the HTML template elsewhere.
We'll write that template in a moment. Before we do, we'll take a step back We'll write that template in a moment. Before we do, we'll take a step back
and revise the `app.module.ts` and `app.component.ts` to make use of our new `HeroFormComponent`. and revise the `app.module.ts` and `app.component.ts` to make use of our new `HeroFormComponent`.
@ -191,7 +191,7 @@ code-example(format="").
.alert.is-important .alert.is-important
:marked :marked
If a component, directive, or pipe belongs to a module in the `imports` array, _DON'T_ declare it in the `declarations` array. If a component, directive, or pipe belongs to a module in the `imports` array, _DON'T_ declare it in the `declarations` array.
If you wrote it and it should belong to this module, _DO_ declare it in the `declarations` array. If you wrote it and it should belong to this module, _DO_ declare it in the `declarations` array.
.l-main-section .l-main-section
@ -230,7 +230,7 @@ code-example(format="").
**We are not using Angular yet**. There are no bindings. No extra directives. Just layout. **We are not using Angular yet**. There are no bindings. No extra directives. Just layout.
The `container`, `form-group`, `form-control`, and `btn` classes The `container`, `form-group`, `form-control`, and `btn` classes
come from [Twitter Bootstrap](http://getbootstrap.com/css/). Purely cosmetic. come from [Twitter Bootstrap](http://getbootstrap.com/css/). Purely cosmetic.
We're using Bootstrap to gussy up our form. We're using Bootstrap to gussy up our form.
Hey, what's a form without a little style! Hey, what's a form without a little style!
@ -300,7 +300,7 @@ figure.image-display
We appended a diagnostic interpolation after the input tag We appended a diagnostic interpolation after the input tag
so we can see what we're doing. so we can see what we're doing.
We left ourselves a note to throw it away when we're done. We left ourselves a note to throw it away when we're done.
:marked :marked
Focus on the binding syntax: `[(ngModel)]="..."`. Focus on the binding syntax: `[(ngModel)]="..."`.
@ -314,13 +314,13 @@ figure.image-display
The diagnostic is evidence that we really are flowing values from the input box to the model and The diagnostic is evidence that we really are flowing values from the input box to the model and
back again. **That's two-way data binding!** back again. **That's two-way data binding!**
Notice that we also added a `name` attribute to our `<input>` tag and set it to "name" Notice that we also added a `name` attribute to our `<input>` tag and set it to "name"
which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful. which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful.
Defining a `name` attribute is a requirement when using `[(ngModel)]` in combination with a form. Defining a `name` attribute is a requirement when using `[(ngModel)]` in combination with a form.
.l-sub-section .l-sub-section
:marked :marked
Internally Angular creates `FormControls` and registers them with an `NgForm` directive that Angular Internally Angular creates `FormControls` and registers them with an `NgForm` directive that Angular
attached to the `<form>` tag. Each `FormControl` is registered under the name we assigned to the `name` attribute. attached to the `<form>` tag. Each `FormControl` is registered under the name we assigned to the `name` attribute.
We'll talk about `NgForm` [later in this chapter](#ngForm). We'll talk about `NgForm` [later in this chapter](#ngForm).
@ -340,7 +340,7 @@ figure.image-display
- Each input element has an `id` property that is used by the `label` element's `for` attribute - Each input element has an `id` property that is used by the `label` element's `for` attribute
to match the label to it's input control. to match the label to it's input control.
- Each input element has a `name` property that is required by Angular Forms to register the control with the form. - Each input element has a `name` property that is required by Angular Forms to register the control with the form.
:marked :marked
If we ran the app right now and changed every Hero model property, the form might display like this: If we ran the app right now and changed every Hero model property, the form might display like this:
figure.image-display figure.image-display
@ -355,7 +355,7 @@ figure.image-display
:marked :marked
### Inside [(ngModel)] ### Inside [(ngModel)]
*This section is an optional deep dive into [(ngModel)]. 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. The punctuation in the binding syntax, <span style="font-family:courier"><b>[()]</b></span>, is a good clue to what's going on.
In a Property Binding, a value flows from the model to a target property on screen. In a Property Binding, a value flows from the model to a target property on screen.
@ -405,7 +405,7 @@ figure.image-display
The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state. The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state.
We can leverage those class names to change the appearance of the We can leverage those class names to change the appearance of the
control and make messages appear or disappear. control and make messages appear or disappear.
table table
tr tr
th State th State
@ -491,32 +491,32 @@ figure.image-display
1. the "*is required*" message in a nearby `<div>` which we'll display only if the control is invalid. 1. the "*is required*" message in a nearby `<div>` which we'll display only if the control is invalid.
Here's how we do it for the *name* input box: Here's how we do it for the *name* input box:
+makeExample('forms/ts/app/hero-form.component.html', +makeExample('forms/ts/app/hero-form.component.html',
'name-with-error-msg', 'name-with-error-msg',
'app/hero-form.component.html (excerpt)')(format=".") 'app/hero-form.component.html (excerpt)')(format=".")
:marked :marked
We need a template reference variable to access the input box's Angular control from within the template. We need a template reference variable to access the input box's Angular control from within the template.
Here we created a variable called `name` and gave it the value "ngModel". Here we created a variable called `name` and gave it the value "ngModel".
.l-sub-section .l-sub-section
:marked :marked
Why "ngModel"? Why "ngModel"?
A directive's [exportAs](../api/core/index/DirectiveMetadata-class.html#!#exportAs-anchor) property A directive's [exportAs](../api/core/index/DirectiveMetadata-class.html#!#exportAs-anchor) property
tells Angular how to link the reference variable to the directive. tells Angular how to link the reference variable to the directive.
We set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel". We set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel".
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. 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.
+makeExample('forms/ts/app/hero-form.component.html', +makeExample('forms/ts/app/hero-form.component.html',
'hidden-error-msg', 'hidden-error-msg',
'app/hero-form.component.html (excerpt)') 'app/hero-form.component.html (excerpt)')
:marked :marked
In this example, we hide the message when the control is valid or pristine; In this example, we hide the message when the control is valid or pristine;
pristine means the user hasn't changed the value since it was displayed in this form. pristine means the user hasn't changed the value since it was displayed in this form.
This user experience is the developer's choice. Some folks want to see the message at all times. This user experience is the developer's choice. Some folks want to see the message at all times.
If we ignore the `pristine` state, we would hide the message only when the value is valid. If we ignore the `pristine` state, we would hide the message only when the value is valid.
If we arrive in this component with a new (blank) hero or an invalid hero, If we arrive in this component with a new (blank) hero or an invalid hero,
we'll see the error message immediately, before we've done anything. we'll see the error message immediately, before we've done anything.
Some folks find that behavior disconcerting. They only want to see the message when the user makes an invalid change. Some folks find that behavior disconcerting. They only want to see the message when the user makes an invalid change.
Hiding the message while the control is "pristine" achieves that goal. Hiding the message while the control is "pristine" achieves that goal.
We'll see the significance of this choice when we [add a new hero](#new-hero) to the form. We'll see the significance of this choice when we [add a new hero](#new-hero) to the form.
@ -527,30 +527,30 @@ figure.image-display
We can add the same kind of error handling to the `<select>` if we want We can add the same kind of error handling to the `<select>` if we want
but it's not imperative because the selection box already constrains the but it's not imperative because the selection box already constrains the
power to valid value. power to valid value.
<a id="new-hero"></a> <a id="new-hero"></a>
<a id="reset"></a> <a id="reset"></a>
.l-main-section .l-main-section
:marked :marked
## Add a hero and reset the form ## Add a hero and reset the form
We'd like to add a new hero in this form. We'd like to add a new hero in this form.
We place a "New Hero" button at the bottom of the form and bind its click event to a component method. We place a "New Hero" button at the bottom of the form and bind its click event to a component method.
+makeExample('forms/ts/app/hero-form.component.html', +makeExample('forms/ts/app/hero-form.component.html',
'new-hero-button', 'new-hero-button',
'app/hero-form.component.html (New Hero button)') 'app/hero-form.component.html (New Hero button)')
:marked :marked
+makeExample('forms/ts/app/hero-form.component.ts', +makeExample('forms/ts/app/hero-form.component.ts',
'new-hero-v1', 'new-hero-v1',
'app/hero-form.component.ts (New Hero method - v1)')(format=".") 'app/hero-form.component.ts (New Hero method - v1)')(format=".")
:marked :marked
Run the application again, click the *New Hero* button, and the form clears. Run the application again, click the *New Hero* button, and the form clears.
The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties. The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
That's understandable as these are required fields. That's understandable as these are required fields.
The error messages are hidden because the form is pristine; we haven't changed anything yet. The error messages are hidden because the form is pristine; we haven't changed anything yet.
Enter a name and click *New Hero* again. Enter a name and click *New Hero* again.
This time we see an error message! Why? We don't want that when we display a new (empty) hero. This time we see an error message! Why? We don't want that when we display a new (empty) hero.
Inspecting the element in the browser tools reveals that the *name* input box is no longer pristine. Inspecting the element in the browser tools reveals that the *name* input box is no longer pristine.
Replacing the hero *did not restore the pristine state* of the control. Replacing the hero *did not restore the pristine state* of the control.
.l-sub-section .l-sub-section
@ -559,26 +559,26 @@ figure.image-display
replacing the entire hero and clearing the `name` property programmatically. replacing the entire hero and clearing the `name` property programmatically.
Angular makes no assumptions and leaves the control in its current, dirty state. Angular makes no assumptions and leaves the control in its current, dirty state.
:marked :marked
We'll have to reset the form controls manually with a small trick. We'll have to reset the form controls manually with a small trick.
We add an `active` flag to the component, initialized to `true`. When we add a new hero, We add an `active` flag to the component, initialized to `true`. When we add a new hero,
we toggle `active` false and then immediately back to true with a quick `setTimeout`. we toggle `active` false and then immediately back to true with a quick `setTimeout`.
+makeExample('forms/ts/app/hero-form.component.ts', +makeExample('forms/ts/app/hero-form.component.ts',
'new-hero', 'new-hero',
'app/hero-form.component.ts (New Hero method - final)')(format=".") 'app/hero-form.component.ts (New Hero method - final)')(format=".")
:marked :marked
Then we bind the form element to this `active` flag. Then we bind the form element to this `active` flag.
+makeExample('forms/ts/app/hero-form.component.html', +makeExample('forms/ts/app/hero-form.component.html',
'form-active', 'form-active',
'app/hero-form.component.html (Form tag)') 'app/hero-form.component.html (Form tag)')
:marked :marked
With `NgIf` bound to the `active` flag, With `NgIf` bound to the `active` flag,
clicking "New Hero" removes the form from the DOM and recreates it in a blink of an eye. clicking "New Hero" removes the form from the DOM and recreates it in a blink of an eye.
The re-created form is in a pristine state. The error message is hidden. The re-created form is in a pristine state. The error message is hidden.
.l-sub-section .l-sub-section
:marked :marked
This is a temporary workaround while we await a proper form reset feature. This is a temporary workaround while we await a proper form reset feature.
:marked :marked
.l-main-section .l-main-section
:marked :marked
## Submit the form with **ngSubmit** ## Submit the form with **ngSubmit**
@ -602,7 +602,7 @@ figure.image-display
:marked :marked
### The NgForm directive ### The NgForm directive
What `NgForm` directive? We didn't add an [NgForm](../api/common/index/NgForm-directive.html) directive! What `NgForm` directive? We didn't add an [NgForm](../api/common/index/NgForm-directive.html) directive!
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically. Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
The `NgForm` directive supplements the `form` element with additional features. The `NgForm` directive supplements the `form` element with additional features.
@ -610,7 +610,7 @@ figure.image-display
and monitors their properties including their validity. and monitors their properties including their validity.
It also has its own `valid` property which is true only *if every contained It also has its own `valid` property which is true only *if every contained
control* is valid. control* is valid.
:marked :marked
Later in the template we bind the button's `disabled` property to the form's over-all validity via Later in the template we bind the button's `disabled` property to the form's over-all validity via
the `heroForm` variable. Here's that bit of markup: the `heroForm` variable. Here's that bit of markup:
@ -686,7 +686,7 @@ figure.image-display
- A form component class with a `Component` decorator. - A form component class with a `Component` decorator.
- The `ngSubmit` directive for handling the form submission. - The `ngSubmit` directive for handling the form submission.
- Template reference variables such as `#heroForm`, `#name` and `#power`. - Template reference variables such as `#heroForm`, `#name` and `#power`.
- The `[(ngModel)]` syntax and a `name` attribute for two-way data binding, validation and change tracking. - The `[(ngModel)]` syntax and a `name` attribute for two-way data binding, validation and change tracking.
- The reference variables `valid` property on input controls to check if a control is valid and show/hide error messages. - The reference variables `valid` property on input controls to check if a control is valid and show/hide error messages.
- Controlling the submit button's enabled state by binding to `NgForm` validity. - Controlling the submit button's enabled state by binding to `NgForm` validity.
- Custom CSS classes that provide visual feedback to users about invalid controls. - Custom CSS classes that provide visual feedback to users about invalid controls.
@ -704,7 +704,7 @@ figure.image-display
.file hero-form.component.ts .file hero-form.component.ts
.file main.ts .file main.ts
.file node_modules ... .file node_modules ...
.file typings ... .file typings ...
.file index.html .file index.html
.file package.json .file package.json
.file tsconfig.json .file tsconfig.json
@ -718,12 +718,12 @@ figure.image-display
forms/ts/app/hero.ts, forms/ts/app/hero.ts,
forms/ts/app/app.module.ts, forms/ts/app/app.module.ts,
forms/ts/app/app.component.ts, forms/ts/app/app.component.ts,
forms/ts/app/main.ts, forms/ts/app/main.ts,
forms/ts/index.html, forms/ts/index.html,
forms/ts/forms.css`, forms/ts/forms.css`,
'final, final,,,,,', 'final, final,,,,,',
`hero-form.component.ts, `hero-form.component.ts,
hero-form.component.html, hero-form.component.html,
hero.ts, hero.ts,
app.module.ts, app.module.ts,
app.component.ts, app.component.ts,

View File

@ -6,7 +6,7 @@ include ../_util-fns
In this chapter we learn to bind to those events using the Angular In this chapter we learn to bind to those events using the Angular
event binding syntax. event binding syntax.
<live-example>Run the live example</live-example>. Run the <live-example></live-example>.
:marked :marked
## Binding to user input events ## Binding to user input events