(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", "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." "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": { "pipes": {
"title": "Pipes", "title": "Pipes",
"intro": "Pipes transform displayed values within a template" "intro": "Pipes transform displayed values within a template"
@ -28,11 +33,6 @@
"title": "Template Syntax", "title": "Template Syntax",
"intro": "How to write templates that display data and consume user events with the help of data binding." "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": { "dependency-injection": {
"title": "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”. Thats “HTML Plus”.
Now we are learning about data binding. At first glance it appears that we are setting attributes, 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> <button [disabled]="isUnchanged">Save</button>
``` ```
@ -225,27 +225,52 @@ table
Our intuition is wrong! Our everyday HTML mental model is misleading us. 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. 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. .l-sub-section
If we were trying to disable a button in static HTML, we would add the `disabled` attribute to it. :markdown
To enable the button, we'd omit or remove the `disabled` attribtue. ### HTML Attribute vs. DOM Property
```
<button>Enabled</button> The distinction between an HTML attribute and a DOM property is crucial to understanding how Angular binding works.
<button disabled>Disabled</button>
``` **Attributes are defined by HTML. Properties are defined by DOM (the Document Object Model).**
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.
On the other hand, setting the button's `disabled` *property* via a data binding does exactly what we expect. * A few HTML attributes have 1:1 mapping to properties. `id` is one example.
```
<button [disabled]="true">Disabled</button> * Some HTML attributes don't have corresponding properties. `colspan` is one example.
<button [disabled]="false">Enabled</button>
``` * 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. This is so important, well say it again.
**Template binding works with *properties* and *events*, not *attributes*.** **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