(docs) forms - code maintained by _examples

Includes template-syntax.jade clarification on attributes v properties
This commit is contained in:
Ward Bell 2015-10-20 16:10:44 -07:00 committed by Naomi Black
parent f10a2e906a
commit 963f67ea07
22 changed files with 946 additions and 466 deletions

View File

@ -0,0 +1 @@
src/**/*.js

View File

@ -0,0 +1,22 @@
{
"name": "angular2-getting-started",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"tsc": "tsc -p src -w",
"start": "live-server --open=src"
},
"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"
}
}

View File

@ -0,0 +1,12 @@
// #docregion
import {bootstrap, Component} from 'angular2/angular2'
import {HeroFormComponent} from './hero-form.component'
@Component({
selector: 'my-app',
template: '<hero-form></hero-form>',
directives: [HeroFormComponent]
})
class AppComponent { }
bootstrap(AppComponent);

View File

@ -0,0 +1,196 @@
<!--#docplaster
-->
<!-- #docregion final -->
<div class="container">
<!-- #docregion edit-div -->
<div [hidden]="submitted">
<h1>Hero Form</h1>
<!-- #docregion ng-submit -->
<form (ng-submit)="onSubmit()" #hf="form">
<!-- #enddocregion edit-div -->
<!-- #enddocregion ng-submit -->
<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" >
<div [hidden]="name.valid" class="alert alert-danger">
Name is required
</div>
<!-- #enddocregion name-with-error-msg -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="model.alterEgo"
ng-control="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ng-model)]="model.power"
ng-control="power" #power="form" >
<option *ng-for="#p of powers" [value]="p">{{p}}</option>
</select>
<div [hidden]="power.valid" class="alert alert-danger">
Power is required
</div>
</div>
<!-- #docregion submit-button -->
<button type="submit" class="btn btn-default"
[disabled]="!hf.form.valid">Submit</button>
<!-- #enddocregion submit-button -->
</form>
</div>
<!-- #docregion submitted -->
<div [hidden]="!submitted">
<h2>You submitted the following:</h2>
<div class="row">
<div class="col-xs-3">Name</div>
<div class="col-xs-9 pull-left">{{ model.name }}</div>
</div>
<div class="row">
<div class="col-xs-3">Alter Ego</div>
<div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
</div>
<div class="row">
<div class="col-xs-3">Power</div>
<div class="col-xs-9 pull-left">{{ model.power }}</div>
</div>
<br>
<button class="btn btn-default" (click)="submitted=false">Edit</button>
</div>
<!-- #enddocregion submitted -->
</div>
<!-- #enddocregion final -->
<!-- ==================================================== -->
<div>
<form>
<!-- #docregion edit-div -->
<!-- ... all of the form ... -->
</form>
</div>
<!-- #enddocregion edit-div -->
<!-- ==================================================== -->
<hr>
<style>
.no-style .ng-valid {
border-left: 1px solid #CCC
}
.no-style .ng-invalid {
border-left: 1px solid #CCC
}
</style>
<div class="no-style" style="margin-left: 4px">
<!-- #docregion start -->
<div class="container">
<h1>Hero Form</h1>
<form>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required>
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control">
</div>
<!-- #enddocregion start -->
<!-- #docregion powers -->
<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>
</select>
</div>
<!-- #enddocregion powers -->
<!-- #docregion start -->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion start -->
<!-- #enddocregion phase1-->
<!-- ==================================================== -->
<hr>
<!-- #docregion phase2-->
<div class="container">
<h1>Hero Form</h1>
<form>
<!-- #docregion ng-model-2-->
{{diagnostic}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required
[(ng-model)]="model.name" >
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ng-model)]="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>
</select>
</div>
<!-- #enddocregion ng-model-2-->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion phase2-->
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
<hr>
<!-- #docregion ng-model-1-->
<input type="text" class="form-control" required
[(ng-model)]="model.name" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ng-model-1-->
<hr>
<!-- #docregion ng-model-3-->
<input type="text" class="form-control" required
[ng-model]="model.name"
(ng-model-change)="model.name = $event" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ng-model-3-->
<hr>
<form>
<!-- #docregion ng-control-1 -->
<input type="text" class="form-control" required
[(ng-model)]="model.name"
ng-control="name" >
<!-- #enddocregion ng-control-1 -->
<hr>
<!-- #docregion ng-control-2 -->
<input type="text" class="form-control" required
[(ng-model)]="model.name"
ng-control="name" #spy >
TODO: remove this: {{spy.className}}
<!-- #enddocregion ng-control-2 -->
</form>
<div>
<hr>
Name via form.controls = {{showFormControls(hf)}}
</div>
</div>

View File

@ -0,0 +1,48 @@
// #docplaster
// #docregion
// #docregion first, final
import {Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2';
import { Hero } from './hero';
@Component({
selector: 'hero-form',
templateUrl: 'app/hero-form.component.html',
// #docregion directives
directives: [CORE_DIRECTIVES, FORM_DIRECTIVES]
// #enddocregion
})
export class HeroFormComponent {
powers = ['Really Smart', 'Super Flexible',
'Super Hot', 'Weather Changer'];
model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
// #docregion submitted
submitted = false;
onSubmit() { this.submitted = true; }
// #enddocregion submitted
// #enddocregion final
// TODO: Remove this when we're done
get diagnostic() { return JSON.stringify(this.model); }
// #enddocregion first
//////// DO NOT SHOW IN DOCS ////////
// Reveal in html:
// AlterEgo via form.controls = {{showFormControls(hf)}}
showFormControls(form){
return form.controls.alterEgo &&
// #docregion form-controls
form.controls.name.value; // Dr. IQ
// #enddocregion form-controls
}
/////////////////////////////
// #docregion first, final
}
// #enddocregion first, final

View File

@ -0,0 +1,11 @@
// #docregion
export class Hero {
constructor(
public id: number,
public name: string,
public power: string,
public alterEgo?: string
) { }
}

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<title>Hero Form</title>
<!-- #docregion bootstrap -->
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
<!-- #enddocregion bootstrap -->
<link rel="stylesheet" href="styles.css">
<!-- #docregion libraries -->
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
<!-- #enddocregion libraries -->
<!-- #docregion systemjs -->
<script>
System.config({
packages: {'app': {defaultExtension: 'js'}}
});
System.import('app/app');
</script>
<!-- #enddocregion systemjs -->
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -0,0 +1,9 @@
/* #docregion */
.ng-valid[required] {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid {
border-left: 5px solid #a94442; /* red */
}
/* #enddocregion */

View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
}
}

View File

@ -18,7 +18,12 @@
"title": "User Input",
"intro": "User input triggers DOM events. We listen to those events with EventBindings that funnel updated values back into our components and models."
},
"forms": {
"title": "Forms",
"intro": "A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors."
},
"pipes": {
"title": "Pipes",
"intro": "Pipes transform displayed values within a template"
@ -28,11 +33,6 @@
"title": "Template Syntax",
"intro": "How to write templates that display data and consume user events with the help of data binding."
},
"forms": {
"title": "Angular 2 Forms",
"intro": "Learn about the different approaches we can take when building forms and see examples of them in action."
},
"dependency-injection": {
"title": "Dependency Injection",

File diff suppressed because it is too large Load Diff

View File

@ -215,7 +215,7 @@ table
Thats “HTML Plus”.
Now we are learning about data binding. At first glance it appears that we are setting attributes,
as when we bind button `disabled` to the components `isUnchanged` data property:
as when we bind button `disabled` to the components `isUnchanged` property:
```
<button [disabled]="isUnchanged">Save</button>
```
@ -225,27 +225,52 @@ table
Our intuition is wrong! Our everyday HTML mental model is misleading us.
In fact, once we start data binding, we are no longer working with HTML *attributes*. We aren't setting attributes.
We are setting the *properties* of elements, components, and directives.
We are setting the *properties* of DOM elements, Components, and Directives.
The disabled button example may help make this distinction clear.
If we were trying to disable a button in static HTML, we would add the `disabled` attribute to it.
To enable the button, we'd omit or remove the `disabled` attribtue.
```
<button>Enabled</button>
<button disabled>Disabled</button>
```
We'd get a pretty surprising result if we tried to set the `disabled` attribute.
```
<button disabled=false>Still disabled<button>
```
Say what!?!? Setting the `disabled` attribute to false does not enable the button.
In fact, any mention of the `disabled` attribute disables the button, regardless of the value.
.l-sub-section
:markdown
### HTML Attribute vs. DOM Property
The distinction between an HTML attribute and a DOM property is crucial to understanding how Angular binding works.
**Attributes are defined by HTML. Properties are defined by DOM (the Document Object Model).**
On the other hand, setting the button's `disabled` *property* via a data binding does exactly what we expect.
```
<button [disabled]="true">Disabled</button>
<button [disabled]="false">Enabled</button>
```
* A few HTML attributes have 1:1 mapping to properties. `id` is one example.
* Some HTML attributes don't have corresponding properties. `colspan` is one example.
* Some DOM properties don't have corresponding attributes. `textContent` is one example.
* Many HTML attributes appear to map to properties ... but not the way we think!
That last category can be especially confusing ... until we understand this general rule:
**Attributes *initialize* DOM properties and then they are done.
Property values may change; attribute values don't.**
For example, when the browser renders `<input type="text" value="Bob">`, it creates a
corresponding DOM node with a `value` property *initialized* to "Bob".
When the user enters "Sally" into the input box, the DOM element `value` *property* becomes "Sally".
But the HTML `value` *attribute* remains unchanged as we discover if we ask the input element
about that attribute: `input.getAttribute('value') // returns "Bob"`
The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value.
The `disabled` attribute is another peculiar example. A button's `disabled` *property* is
`false` by default so the button is enabled.
When we add the `disabled` *attribute*, it's presence alone initializes the button's `disabled` *property* to `true`
so the button is disabled.
Adding and removing the `disabled` *attribute* disables and enables the button. The value of the *attribute* is irrelevant
which is why we cannot enable a button by writing `<button disabled="false">Still Disabled</button>`.
Setting the button's `disabled` *property* (e.g. with an Angular binding) disables or enables the button.
The value of the *property* matters.
**The HTML attribute and the DOM property are not the same thing even when they have the same name.**
:markdown
This is so important, well say it again.
**Template binding works with *properties* and *events*, not *attributes*.**

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB