+ [(ngModel)]="model.name"
+ ngControl="name" #name="ngForm" >
Power is required
@@ -41,7 +41,7 @@
+ [disabled]="!heroForm.form.valid">Submit
@@ -110,7 +110,7 @@
@@ -128,29 +128,29 @@
Hero Form
@@ -159,37 +159,37 @@
-
+
+ [(ngModel)]="model.name" >
TODO: remove this: {{model.name}}
-
+
-
+
+ [ngModel]="model.name"
+ (ngModelChange)="model.name = $event" >
TODO: remove this: {{model.name}}
-
+
- Name via form.controls = {{showFormControls(hf)}}
+ Name via form.controls = {{showFormControls(heroForm)}}
\ No newline at end of file
diff --git a/public/docs/_examples/forms/ts/src/app/hero-form.component.ts b/public/docs/_examples/forms/ts/app/hero-form.component.ts
similarity index 76%
rename from public/docs/_examples/forms/ts/src/app/hero-form.component.ts
rename to public/docs/_examples/forms/ts/app/hero-form.component.ts
index bc82817571..e68d17124e 100644
--- a/public/docs/_examples/forms/ts/src/app/hero-form.component.ts
+++ b/public/docs/_examples/forms/ts/app/hero-form.component.ts
@@ -1,9 +1,9 @@
// #docplaster
// #docregion
// #docregion first, final
-import {Component} from 'angular2/angular2';
-
-import { Hero } from './hero';
+import {Component} from 'angular2/core';
+import {NgForm} from 'angular2/common';
+import { Hero } from './hero';
@Component({
selector: 'hero-form',
@@ -32,10 +32,10 @@ export class HeroFormComponent {
// Reveal in html:
// AlterEgo via form.controls = {{showFormControls(hf)}}
- showFormControls(form){
- return form.controls.alterEgo &&
+ showFormControls(form:NgForm){
+ return form.controls['alterEgo'] &&
// #docregion form-controls
- form.controls.name.value; // Dr. IQ
+ form.controls['name'].value; // Dr. IQ
// #enddocregion form-controls
}
/////////////////////////////
diff --git a/public/docs/_examples/forms/ts/src/app/hero.ts b/public/docs/_examples/forms/ts/app/hero.ts
similarity index 100%
rename from public/docs/_examples/forms/ts/src/app/hero.ts
rename to public/docs/_examples/forms/ts/app/hero.ts
diff --git a/public/docs/_examples/forms/ts/src/index.html b/public/docs/_examples/forms/ts/index.html
similarity index 56%
rename from public/docs/_examples/forms/ts/src/index.html
rename to public/docs/_examples/forms/ts/index.html
index 42fa6ee681..70ebfb1b68 100644
--- a/public/docs/_examples/forms/ts/src/index.html
+++ b/public/docs/_examples/forms/ts/index.html
@@ -5,19 +5,19 @@
Hero Form
-
+
-
+
-
-
+
+
diff --git a/public/docs/_examples/forms/ts/package.json b/public/docs/_examples/forms/ts/package.json
index 5bffa1904d..041d18e248 100644
--- a/public/docs/_examples/forms/ts/package.json
+++ b/public/docs/_examples/forms/ts/package.json
@@ -4,19 +4,12 @@
"description": "",
"main": "index.js",
"scripts": {
- "tsc": "tsc -p src -w",
- "start": "live-server --open=src"
+ "tsc": "tsc",
+ "tsc:w": "tsc -w",
+ "lite": "lite-server",
+ "both": "concurrent \"npm run tsc:w\" \"npm run lite\" "
},
"keywords": [],
"author": "",
- "license": "ISC",
- "dependencies": {
- "angular2": "2.0.0-alpha.44",
- "bootstrap": "^3.3.5",
- "systemjs": "0.19.2"
- },
- "devDependencies": {
- "live-server": "^0.8.1",
- "typescript": "^1.6.2"
- }
+ "license": "ISC"
}
diff --git a/public/docs/_examples/forms/ts/src/plnkr.json b/public/docs/_examples/forms/ts/plnkr.json
similarity index 100%
rename from public/docs/_examples/forms/ts/src/plnkr.json
rename to public/docs/_examples/forms/ts/plnkr.json
diff --git a/public/docs/_examples/forms/ts/src/tsconfig.json b/public/docs/_examples/forms/ts/src/tsconfig.json
deleted file mode 100644
index 6a58b35a58..0000000000
--- a/public/docs/_examples/forms/ts/src/tsconfig.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES5",
- "module": "commonjs",
- "sourceMap": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "removeComments": false,
- "noImplicitAny": false
- }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/forms/ts/src/styles.css b/public/docs/_examples/forms/ts/styles.css
similarity index 100%
rename from public/docs/_examples/forms/ts/src/styles.css
rename to public/docs/_examples/forms/ts/styles.css
diff --git a/public/docs/_examples/forms/ts/tsconfig.json b/public/docs/_examples/forms/ts/tsconfig.json
new file mode 100644
index 0000000000..6ffae9f106
--- /dev/null
+++ b/public/docs/_examples/forms/ts/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "target": "ES5",
+ "module": "system",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "removeComments": false,
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true
+ },
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json
index e72ff7b8c7..92a6a4b31d 100644
--- a/public/docs/_examples/package.json
+++ b/public/docs/_examples/package.json
@@ -15,13 +15,14 @@
"author": "",
"license": "ISC",
"dependencies": {
- "angular2": "^2.0.0-alpha.51",
+ "angular2": "2.0.0-alpha.52",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-alpha.14",
- "zone.js": "0.5.8"
+ "zone.js": "0.5.8",
+ "bootstrap": "^3.3.6"
},
"devDependencies": {
"concurrently": "^1.0.0",
diff --git a/public/docs/ts/latest/guide/forms.jade b/public/docs/ts/latest/guide/forms.jade
index e6c3135806..bd8038eb80 100644
--- a/public/docs/ts/latest/guide/forms.jade
+++ b/public/docs/ts/latest/guide/forms.jade
@@ -1,6 +1,5 @@
include ../../../../_includes/_util-fns
-
:marked
We’ve all used a form to login, submit a help request, place an order, book a flight,
schedule a meeting and perform countless other data entry tasks.
@@ -20,17 +19,17 @@ 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 we can use them to provide strong visual feedback
+ - The special CSS classes that `ngControl` adds to form controls and how we can use them to provide strong visual feedback
- How to display validation errors to users and enable/disable form controls
- How to share information across controls with template local variables
- [Live Example](/resources/live-examples/forms/ts/src/plnkr.html)
+ [Live Example](/resources/live-examples/forms/ts/plnkr.html)
.l-main-section
:marked
## Template-Driven Forms
@@ -51,7 +50,7 @@ include ../../../../_includes/_util-fns
We'll discuss and learn to build the following template-driven form:
figure.image-display
- img(src="/resources/images/devguide/forms/hf-1.png" width="400px" alt="Clean Form")
+ img(src="/resources/images/devguide/forms/heroForm-1.png" width="400px" alt="Clean Form")
:marked
Here at the *Hero Employment Agency* we use this form to maintain personal information about the
@@ -62,7 +61,7 @@ figure.image-display
If we delete the hero name, the form displays a validation error in an attention grabbing style:
figure.image-display
- img(src="/resources/images/devguide/forms/hf-2.png" width="400px" alt="Invalid, Name Required")
+ img(src="/resources/images/devguide/forms/heroForm-2.png" width="400px" alt="Invalid, Name Required")
:marked
Note that the submit button is disabled and the "required" bar to the left of the input control changed from green to red.
@@ -76,11 +75,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. Disable the form’s submit button until the form is valid
:marked
@@ -98,7 +97,7 @@ figure.image-display
Create a new file in the app folder called `hero.ts` and give it the following class definition:
-+makeExample('forms/ts/src/app/hero.ts', null, 'app/hero.ts')
++makeExample('forms/ts/app/hero.ts', null, 'app/hero.ts')
:marked
It's an anemic model with few requirements and no behavior. Perfect for our demo.
@@ -109,10 +108,11 @@ figure.image-display
The `alterEgo` is optional and the constructor lets us omit it; note the (?) in `alterEgo?`.
We can create a new hero like this:
- ```
- let myHero = new Hero(42, 'SkyDog', 'Fetch any object at any distance', 'Leslie Rollover');
+code-example(format="").
+ let myHero = new Hero(42, 'SkyDog',
+ 'Fetch any object at any distance', 'Leslie Rollover');
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
- ```
+:marked
.l-main-section
:marked
@@ -124,7 +124,7 @@ figure.image-display
Create a new file called `hero-form.component.ts` and give it the following definition:
-+makeExample('forms/ts/src/app/hero-form.component.ts', 'first', 'app/hero-form.component.ts')
++makeExample('forms/ts/app/hero-form.component.ts', 'first', 'app/hero-form.component.ts')
:marked
There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component we've written before.
@@ -155,16 +155,16 @@ figure.image-display
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
- and revise the `app.ts` to make use of our new `HeroFormComponent`.
+ and revise the `app.component.ts` to make use of our new `HeroFormComponent`.
.l-main-section
:marked
- ## Revise the *app.ts*
+ ## Revise the *app.component.ts*
- `app.ts` is the application's root component. It will host our new `HeroFormComponent`.
+ `app.component.ts` is the application's root component. It will host our new `HeroFormComponent`.
Replace the contents of the "QuickStart" version with the following:
-+makeExample('forms/ts/src/app/app.ts', null, 'app/app.ts')
++makeExample('forms/ts/app/app.component.ts', null, 'app/app.component.ts')
:marked
.l-sub-section
@@ -184,7 +184,7 @@ figure.image-display
Create a new template file called `hero-form.component.html` and give it the following definition:
-+makeExample('forms/ts/src/app/hero-form.component.html', 'start', 'app/hero-form.component.html')
++makeExample('forms/ts/app/hero-form.component.html', 'start', 'app/hero-form.component.html')
:marked
That is plain old HTML 5. We're presenting two of the `Hero` fields, `name` and `alterEgo`, and
@@ -213,15 +213,15 @@ figure.image-display
Let's add the stylesheet.
ol
- li Open a terminal window and enter the command:
+ li Open a terminal window in the application root folder and enter the command:
code-example(language="html" escape="html").
npm install bootstrap --save
li Open
index.html and add the following link to the
<head>.
- +makeExample('forms/ts/src/index.html', 'bootstrap')(format=".")
+ +makeExample('forms/ts/index.html', 'bootstrap')(format=".")
:marked
.l-main-section
:marked
- ## Add Powers with ***ng-for**
+ ## Add Powers with ***ngFor**
Our hero may choose one super power from a fixed list of Agency-approved powers.
We maintain that list internally (in `HeroFormComponent`).
@@ -230,7 +230,7 @@ ol
a technique we might have seen before in the [Displaying Data](./displaying-data.html) chapter.
Add the following HTML *immediately below* the *Alter Ego* group.
-+makeExample('forms/ts/src/app/hero-form.component.html', 'powers', 'app/hero-form.component.html (excerpt)')
++makeExample('forms/ts/app/hero-form.component.html', 'powers', 'app/hero-form.component.html (excerpt)')(format=".")
:marked
We are repeating the `
` tag for each power in the list of Powers.
@@ -239,11 +239,11 @@ ol
.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
- img(src="/resources/images/devguide/forms/hf-3.png" width="400px" alt="Early form with no binding")
+ img(src="/resources/images/devguide/forms/heroForm-3.png" width="400px" alt="Early form with no binding")
:marked
We don't see hero data because we are not binding to the `Hero` yet.
We know how to do that from earlier chapters.
@@ -259,7 +259,7 @@ figure.image-display
Find the `` tag for the "Name" and update it like this
-+makeExample('forms/ts/src/app/hero-form.component.html', 'ng-model-1')
++makeExample('forms/ts/app/hero-form.component.html', 'ngModel-1','app/hero-form.component.html (excerpt)')(format=".")
.l-sub-section
:marked
@@ -268,42 +268,42 @@ 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 we really are flowing values 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 our form should have three `[(ng-model)]` bindings that
+ After revision the core of our form should have three `[(ngModel)]` bindings that
look much like this:
-+makeExample('forms/ts/src/app/hero-form.component.html', 'ng-model-2', 'app/hero-form.component.html (excerpt)')
++makeExample('forms/ts/app/hero-form.component.html', 'ngModel-2', 'app/hero-form.component.html (excerpt)')
:marked
If we ran the app right now and changed every Hero model property, the form might display like this:
figure.image-display
- img(src="/resources/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ng-model in super action")
+ img(src="/resources/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ngModel in super action")
:marked
The diagnostic near the top of the form
confirms that all of our changes are reflected in the model.
- ** We're done with the diagnostic binding. Delete it now.**
+ **Delete** the `{{diagnostic}}` binding at the top as it has served its purpose.
.l-sub-section
:marked
- ### Inside [(ng-model)]
- *This section is an optional deep dive into [(ng-model)]. Not interested? Skip ahead!*
+ ### Inside [(ngModel)]
+ *This section is an optional deep dive into [(ngModel)]. Not interested? Skip ahead!*
The punctuation in the binding syntax, [()], is a good clue to what's going on.
@@ -320,23 +320,23 @@ figure.image-display
In fact, we can break the `NgModel` binding into its two separate modes
as we do in this re-write of the "Name" `` binding:
- +makeExample('forms/ts/src/app/hero-form.component.html', 'ng-model-3')
+ +makeExample('forms/ts/app/hero-form.component.html', 'ngModel-3','app/hero-form.component.html (excerpt)')(format=".")
:marked
The Property Binding should feel familiar. The Event Binding might seem strange.
- The `ng-model-change` is not an `` element event.
+ The `ngModelChange` is not an `` element event.
It is actually an event property of the `NgModel` directive.
When Angular sees a binding target in the form [(abc)],
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 `ngModelChange` 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? We almost always prefer `[(ng-model)]`.
+ Nice to know but is it practical? We almost always prefer `[(ngModel)]`.
We might split the binding if we had to do something special in
the event handling such as debounce or throttle the key strokes.
@@ -345,7 +345,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.
@@ -365,18 +365,18 @@ figure.image-display
control and make messages appear or disappear.
We'll explore those effects soon. Right now
- we should **add `ng-control`to all three form controls**,
+ we should **add `ngControl`to all three form controls**,
starting with the *Name* input box
-+makeExample('forms/ts/src/app/hero-form.component.html', 'ng-control-1', 'app/hero-form.component.html (excerpt)')
++makeExample('forms/ts/app/hero-form.component.html', 'ngControl-1', 'app/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`.
We didn't add the `NgForm` directive explicitly but it's here
- and we'll talk about it [later in this chapter](#ng-form).
+ and we'll talk about it [later in this chapter](#ngForm).
.l-main-section
:marked
@@ -406,7 +406,7 @@ table
Let's add a temporary [local template variable](./template-syntax.html#local-vars) named **spy**
to the "Name" `` tag and use the spy to display those classes.
-+makeExample('forms/ts/src/app/hero-form.component.html', 'ng-control-2')
++makeExample('forms/ts/app/hero-form.component.html', 'ngControl-2','app/hero-form.component.html (excerpt)')(format=".")
:marked
Now run the app and focus on the *Name* input box.
@@ -438,12 +438,12 @@ figure.image-display
We achieve this effect by adding two styles to a new `styles.css` file
that we add to our project as a sibling to `index.html`.
-+makeExample('forms/ts/src/styles.css',null,'styles.css')
++makeExample('forms/ts/styles.css',null,'styles.css')(format=".")
:marked
These styles select for the two Angular validity classes and the HTML 5 "required" attribute.
We update the `` of the `index.html` to include this style sheet.
-+makeExample('forms/ts/src/index.html', 'styles', 'index.html (excerpt)')(format=".")
++makeExample('forms/ts/index.html', 'styles', 'index.html (excerpt)')(format=".")
:marked
## Show and Hide Validation Error messages
@@ -464,39 +464,36 @@ figure.image-display
Here's how we do it for the *name* input box:
-var stylePattern = { otl: /(#name="form")|(.*div.*$)|(Name is required)/gm };
-+makeExample('forms/ts/src/app/hero-form.component.html',
++makeExample('forms/ts/app/hero-form.component.html',
'name-with-error-msg',
'app/hero-form.component.html (excerpt)',
stylePattern)
:marked
- We initialized the template local variable with the word "form" (`#name="form"`)
+ When we added the `ngControl` directive, we bound it to the the model's `name` property.
+
+ Here we initialize a template local variable (`name`) with the value "ngForm" (`#name="ngForm"`).
+ Angular recognizes that syntax and re-sets the `name` local template variable to the
+ `ngControl` directive instance.
+ In other words, the `name` local template variable becomes a handle on the `ngControl` object
+ for this input box.
- Angular recognizes that syntax and sets the `name` variable
- to the `Control` object identified by the `ng-control` directive which,
- not coincidentally, we called "name".
-
- We bind the `Control` object's `valid` property to the element's `hidden` property.
- While the control is valid, the message is hidden;
- if it becomes invalid, the message is revealed.
-
+ Now we can control visibility of the "name" error message by binding the message `` element's `hidden` property
+ to the `ngControl` object's `valid` property. The message is hidden while the control is valid;
+ the message is revealed when the control becomes invalid.
+
.l-sub-section
:marked
### The NgForm directive
- Recall from the previous section that `ng-control` registered this input box with the
- `NgForm` directive as "name".
-
- We didn't add the **[`NgForm`](../api/core/NgForm-class.html) directive** explicitly.
+ We just set a template local variable with the value of an `NgForm` directive.
+ Why did that work? We didn't add the **[`NgForm`](../api/core/NgForm-class.html) directive** explicitly.
+
Angular added it surreptiously, wrapping it around the `