Merge branch 'api-branch' of https://github.com/angular/angular.io into api-branch
This commit is contained in:
commit
b5fdd6ba52
|
@ -11,12 +11,12 @@
|
|||
"title": "5 Min Quickstart"
|
||||
},
|
||||
|
||||
"resources": {
|
||||
"icon": "play-circle-fill",
|
||||
"title": "Angular Resources",
|
||||
"guide": {
|
||||
"icon": "list",
|
||||
"title": "Step By Step Guide",
|
||||
"banner": "Angular 2 is currently in Alpha Preview. For AngularDart 1.X resources, visit <a href='https://angulardart.org/'>angulardart.org</a>."
|
||||
},
|
||||
|
||||
|
||||
"api": {
|
||||
"icon": "book",
|
||||
"title": "API Proposal"
|
||||
|
|
|
@ -1,35 +1,18 @@
|
|||
{
|
||||
"_listtype": "ordered",
|
||||
|
||||
"setup": {
|
||||
"title": "Getting Started"
|
||||
},
|
||||
|
||||
"displaying-data": {
|
||||
"title": "Displaying Data"
|
||||
},
|
||||
|
||||
"user-input": {
|
||||
"title": "User Input"
|
||||
},
|
||||
|
||||
"making-components": {
|
||||
"title": "Making Components"
|
||||
},
|
||||
|
||||
"talking-to-components": {
|
||||
"title": "Talking to Components"
|
||||
},
|
||||
|
||||
"using-forms": {
|
||||
"title": "Using Forms"
|
||||
},
|
||||
|
||||
"transforming-data": {
|
||||
"title": "Transforming data (pipes)"
|
||||
},
|
||||
|
||||
"reusing-components": {
|
||||
"title": "Reusing Components"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -1,334 +1,304 @@
|
|||
.l-main-section
|
||||
p.
|
||||
Displaying data is job number one for any good application. In Angular, you bind data to elements in HTML
|
||||
templates and Angular automatically updates the UI as data changes.
|
||||
p.
|
||||
Let's walk through how we'd display a property, a list of properties, and then conditionally show content
|
||||
based on state.
|
||||
p.
|
||||
We'll end up with a UI that looks like this:
|
||||
div(align='center')
|
||||
img(src='displaying-data-example1.png')
|
||||
p.
|
||||
Displaying data is job number one for any good application. In Angular, you bind data to elements in HTML
|
||||
templates and Angular automatically updates the UI as data changes.
|
||||
p.
|
||||
Let's walk through how we'd display a property, a list of properties, and then conditionally show content
|
||||
based on state.
|
||||
p.
|
||||
We'll end up with a UI that looks like this:
|
||||
div(align='center')
|
||||
img(src='displaying-data-example1.png')
|
||||
|
||||
.l-main-section
|
||||
h2#section-create-an-entry-point Create an entry point
|
||||
h2#section-create-an-entry-point Create an entry point
|
||||
|
||||
p Open your favorite editor and create a show-properties.html file with the content:
|
||||
pre.prettyprint.linenums.lang-html
|
||||
code.
|
||||
//ES5
|
||||
<display></display>
|
||||
|
||||
pre.prettyprint.linenums.lang-html
|
||||
code.
|
||||
//TypeScript
|
||||
<display></display>
|
||||
|
||||
p
|
||||
| The <code><display></code> component here acts as the site where you'll insert your application.
|
||||
| We'll assume a structure like this for the rest of the examples here and just focus on the parts that
|
||||
| are different.
|
||||
p Open your favorite editor and create a <code>show-properties.html</code> file with the content:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
//show-properties.html
|
||||
<display></display>
|
||||
p
|
||||
| The <code><display></code> component here acts as the site where you'll insert your application.
|
||||
| We'll assume a structure like this for the rest of the examples here and just focus on the parts that
|
||||
| are different.
|
||||
|
||||
.l-main-section
|
||||
h2#section-showing-properties-with-interpolation Showing properties with interpolation
|
||||
p.text-body
|
||||
| The simple method for binding text into templates is through interpolation where you put the name of a property
|
||||
| inside <strong>{{ }}</strong>.
|
||||
h2#section-showing-properties-with-interpolation Showing properties with interpolation
|
||||
p.text-body
|
||||
| The simple method for binding text into templates is through interpolation where you put the name of a property
|
||||
| inside <strong>{{ }}</strong>.
|
||||
|
||||
p To see this working, create another file, <code>show-properties.js</code>, and add the following:
|
||||
p To see this working, create another file, <code>show-properties.dart</code>, and add the following:
|
||||
|
||||
pre.prettyprint.linenums.lang-javascript
|
||||
code.
|
||||
// ES5
|
||||
function DisplayComponent() {
|
||||
this.myName = "Alice";
|
||||
pre.prettyprint.linenums.lang-javascript
|
||||
code.
|
||||
// Dart
|
||||
part of displaying_data;
|
||||
|
||||
@Component(
|
||||
selector: 'display'
|
||||
)
|
||||
|
||||
@View(
|
||||
template: '''
|
||||
<p>My name: {{ myName }}</p>
|
||||
'''
|
||||
)
|
||||
class DisplayComponent {
|
||||
String myName = 'Alice';
|
||||
}
|
||||
DisplayComponent.annotations = [
|
||||
new angular.Component({
|
||||
selector: "display"
|
||||
}),
|
||||
new angular.View({
|
||||
template:
|
||||
'<p>My name: {{ myName }}</p>',
|
||||
directives: [angular.For, angular.If]
|
||||
})
|
||||
];
|
||||
|
||||
pre.prettyprint.linenums.lang-typescript
|
||||
code.
|
||||
// TypeScript
|
||||
import {Component, View, bootstrap, For} from 'angular2/angular2';
|
||||
p.
|
||||
You've just defined a component that encompases a view and controller for the app. The view
|
||||
defines a template:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>My name: {{ myName }}</p>
|
||||
|
||||
@Component({
|
||||
selector: 'display'
|
||||
})
|
||||
@View({
|
||||
template: `
|
||||
<p>My name: {{ myName }}</p>
|
||||
`,
|
||||
directives: [For]
|
||||
})
|
||||
class DisplayComponent {
|
||||
myName: string;
|
||||
todos: Array<string>;
|
||||
p.
|
||||
Angular will automatically pull the value of <code>myName</code> and insert it into the browser and
|
||||
update it whenever it changes without work on your part.
|
||||
|
||||
constructor() {
|
||||
this.myName = "Alice";
|
||||
}
|
||||
}
|
||||
p.
|
||||
One thing to notice here is that though you've written your <code>DisplayComponent</code> class, you haven't
|
||||
called new to create one anywhere. By associating your class with elements named 'display' in
|
||||
the DOM, Angular knows to automatically call new on <code>DisplayComponent</code> and bind its properties to
|
||||
that part of the template.
|
||||
|
||||
p.
|
||||
When you're building templates, data bindings like these have access to the same scope of
|
||||
properties as your controller class does. Here, your class is the <code>DisplayComponent</code> that has
|
||||
just one property, myName.
|
||||
|
||||
.callout.is-helpful
|
||||
header Note
|
||||
p.
|
||||
You've just defined a component that encompases a view and controller for the app. The view
|
||||
defines a template:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>My name: {{ myName }}</p>
|
||||
While you've used <code>template:</code> to specify an inline view, for larger templates you'd
|
||||
want to move them to a separate file and load them with <code>templateUrl:</code> instead.
|
||||
|
||||
p.
|
||||
Angular will automatically pull the value of <code>myName</code> and insert it into the browser and
|
||||
update it whenever it changes without work on your part.
|
||||
p So you can see Angular dynamically update content, add a line after
|
||||
|
||||
p.
|
||||
One thing to notice here is that though you've written your <code>DisplayComponent</code> class, you haven't
|
||||
called new to create one anywhere. By associating your class with elements named 'display' in
|
||||
the DOM, Angular knows to automatically call new on <code>DisplayComponent</code> and bind its properties to
|
||||
that part of the template.
|
||||
|
||||
p.
|
||||
When you're building templates, data bindings like these have access to the same scope of
|
||||
properties as your controller class does. Here, your class is the <code>DisplayComponent</code> that has
|
||||
just one property, myName.
|
||||
|
||||
.callout.is-helpful
|
||||
header Note
|
||||
p.
|
||||
While you've used <code>template:</code> to specify an inline view, for larger templates you'd
|
||||
want to move them to a separate file and load them with <code>templateUrl:</code> instead.
|
||||
|
||||
p So you can see Angular dynamically update content, add a line after
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>My name: {{ myName }}</p>
|
||||
p to this:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>Current time: {{ time }}</p>
|
||||
p.
|
||||
Then give the <code>DisplayComponent</code> a starting value for time and a call to update time
|
||||
via <code>setInterval</code>.
|
||||
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
setInterval(function () { this.time = (new Date()).toString(); }.bind(this), 1000);
|
||||
p Reload the page in your browser and you'll now see the seconds updating automatically.
|
||||
.l-main-section
|
||||
h2#Create-an-array Create an array property and use For on the view
|
||||
p Moving up from a single property, create an array to display as a list.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
//ES5
|
||||
function DisplayComponent() {
|
||||
this.myName = "Alice";
|
||||
this.names = ["Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
pre.prettyprint.lang-typescript
|
||||
code.
|
||||
//Typescript
|
||||
constructor() {
|
||||
this.myName = "Alice";
|
||||
this.names = ["Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
p.
|
||||
You can then use this array in your template with the <code>for</code> directive to create copies of DOM elements
|
||||
with one for each item in the array.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
//ES5
|
||||
template:
|
||||
'<p>My name: {{ myName }}</p>' +
|
||||
'<p>Friends:</p>' +
|
||||
'<ul>' +
|
||||
'<li *for="#name of names">' +
|
||||
'{{ name }}' +
|
||||
'</li>' +
|
||||
'</ul>',
|
||||
|
||||
pre.prettyprint.lang-typescript
|
||||
code.
|
||||
//Typescript
|
||||
template: `
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>My name: {{ myName }}</p>
|
||||
<p>Friends:</p>
|
||||
<ul>
|
||||
<li *for="#name of names">
|
||||
{{ name }}
|
||||
</li>
|
||||
</ul>
|
||||
`,
|
||||
p.
|
||||
To make this work, you'll also need to add the <code>angular.For</code> directive used by the template so
|
||||
that Angular knows to include it:
|
||||
p to this:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p>Current time: {{ time }}</p>
|
||||
p.
|
||||
Then give the <code>DisplayComponent</code> a starting value for time and a call to update time
|
||||
via <code>setInterval</code>.
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
class DisplayComponent {
|
||||
String myName = 'Alice';
|
||||
String time;
|
||||
Timer _timer;
|
||||
|
||||
DisplayComponent() {
|
||||
_updateTime(null);
|
||||
_timer = new Timer.periodic(new Duration(seconds: 1), _updateTime);
|
||||
}
|
||||
|
||||
_updateTime(Timer _) {
|
||||
time = new DateTime.now().toString();
|
||||
}
|
||||
}
|
||||
|
||||
p Reload the page in your browser and you'll now see the seconds updating automatically.
|
||||
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
//ES5
|
||||
directives: [angular.For]
|
||||
pre.prettyprint.lang-typescript
|
||||
code.
|
||||
//Typescript
|
||||
import {Component, View, bootstrap, For} from
|
||||
...
|
||||
directives: [For]
|
||||
p Reload and you've got your list of friends!
|
||||
p.
|
||||
Again, Angular will mirror changes you make to this list over in the DOM. Add a new item and it appears in your
|
||||
list. Delete one and Angular deletes the <li>. Reorder items and Angular makes the corresponding reorder of
|
||||
the DOM list.
|
||||
p Let's look at the few lines that do the work again:
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
//HTML
|
||||
<li *for="#name of names">
|
||||
{{ name }}
|
||||
</li>
|
||||
p The way to read this is:
|
||||
ul
|
||||
li.
|
||||
<code>*for</code> : create a DOM element for each item in an
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">iterable</a>
|
||||
like an array
|
||||
li <code>#name</code> : refer to individual values of the iterable as 'name'
|
||||
li <code>of names</code> : the iterable to use is called 'names' in the current controller
|
||||
p Using this syntax, you can build UI lists from any iterable object.
|
||||
.l-main-section
|
||||
h2#Create-a-class Create a class for the array property and inject into component
|
||||
p.
|
||||
Before we get too much further, we should mention that putting our model (array) directly in our controller isn't
|
||||
proper form. We should separate the concerns by having another class serve the role of model and inject it into
|
||||
the controller.
|
||||
p Make a <code>FriendsService</code> class to provide the model with the list of friends.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
function FriendsService() {
|
||||
this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
p.
|
||||
Replace the current list of friends in DisplayComponent by passing in the FriendsService and setting the list of
|
||||
names in DisplayComponent to the names provided by the service you passed in.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
function DisplayComponent(friends) {
|
||||
this.myName = "Alice";
|
||||
this.names = friends.names;
|
||||
}
|
||||
p And then make FriendsService available to dependency injection
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
DisplayComponent.annotations = [
|
||||
new angular.Component({
|
||||
selector: "display",
|
||||
injectables: [FriendsService]
|
||||
}),
|
||||
...
|
||||
DisplayComponent.parameters = [[FriendsService]];
|
||||
.callout.is-helpful
|
||||
header ES5 Note
|
||||
p.
|
||||
The dependency injection syntax here is using the low-level API and is...well...not very nice. We're
|
||||
working on sugaring the syntax to match the way it works in Angular 1. Expect this to change soon.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
//ES5
|
||||
function FriendsService() {
|
||||
this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
function DisplayComponent(friends) {
|
||||
this.myName = "Alice";
|
||||
this.names = friends.names;
|
||||
}
|
||||
DisplayComponent.annotations = [
|
||||
new angular.Component({
|
||||
selector: "display",
|
||||
injectables: [FriendsService]
|
||||
}),
|
||||
new angular.View({
|
||||
template: '{{ myName }} <ul> <li *for="#name of names"<{{ name }}>/li< >/ul<',
|
||||
directives: [angular.For, angular.If]
|
||||
})
|
||||
];
|
||||
DisplayComponent.parameters = [[FriendsService]];
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
angular.bootstrap(DisplayComponent);
|
||||
});
|
||||
pre.prettyprint.lang-typescript
|
||||
code.
|
||||
//TypeScript
|
||||
import {Component, View, bootstrap, For} from
|
||||
...
|
||||
directives: [For]
|
||||
h2#Create-an-array Create an array property and use For on the view
|
||||
p Moving up from a single property, create an array to display as a list.
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
class DisplayComponent {
|
||||
String myName = 'Alice';
|
||||
List<String> friendNames = ['Aarav', 'Martín', 'Shannon', 'Ariana', 'Kai'];
|
||||
...
|
||||
}
|
||||
|
||||
p.
|
||||
You can then use this array in your template with the <code>for</code> directive to create copies of DOM elements
|
||||
with one for each item in the array.
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
//Dart
|
||||
template: '''
|
||||
<p>My name: {{ myName }}</p>
|
||||
<p>Friends:</p>
|
||||
<ul>
|
||||
<li *for="#name of friendNames">
|
||||
{{ name }}
|
||||
</li>
|
||||
</ul>
|
||||
''',
|
||||
|
||||
p.
|
||||
To make this work, you'll also need to add the <code>angular.For</code> directive used by
|
||||
the template to <code>show_properties.dart</code> so that Angular knows to include it:
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
directives: const[For]
|
||||
|
||||
p Reload and you've got your list of friends!
|
||||
p.
|
||||
Again, Angular will mirror changes you make to this list over in the DOM. Add a new item and it appears in your
|
||||
list. Delete one and Angular deletes the <li>. Reorder items and Angular makes the corresponding reorder of
|
||||
the DOM list.
|
||||
|
||||
p Let's look at the few lines that do the work again:
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<li *for="#name of friendNames">
|
||||
{{ name }}
|
||||
</li>
|
||||
|
||||
p The way to read this is:
|
||||
ul
|
||||
li.
|
||||
<code>*for</code> : create a DOM element for each item in an
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">iterable</a>
|
||||
like an array
|
||||
li <code>#name</code> : refer to individual values of the iterable as 'name'
|
||||
li <code>of friendNames</code> : the iterable to use is called 'friendNames' in the current controller
|
||||
|
||||
p Using this syntax, you can build UI lists from any iterable object.
|
||||
|
||||
.l-main-section
|
||||
h2#Conditionally-displaying-data-with-If Conditionally displaying data with If
|
||||
p.
|
||||
Lastly, before we move on, let's handle showing parts of our UI conditionally with <code>If</code>. The
|
||||
<code>If</code> directive adds or removes elements from the DOM based on the expression you provide.
|
||||
p See it in action by adding a paragraph at the end of your template
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p *if="names.length > 3">You have many friends!</p>
|
||||
p You'll also need to add the If directive so Angular knows to include it.
|
||||
p [TODO: CODE]
|
||||
p.
|
||||
As there are currently 5 items it the list, you'll see the message congratulating you on your many friends.
|
||||
Remove two items from the list, reload your browser, and see that the message no longer displays.
|
||||
pre.prettyprint.lang-javascript
|
||||
code.
|
||||
//ES5
|
||||
function DisplayComponent() {
|
||||
this.myName = "Alice";
|
||||
this.names = ["Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
DisplayComponent.annotations = [
|
||||
new angular.Component({
|
||||
selector: "display"
|
||||
}),
|
||||
new angular.View({
|
||||
template:
|
||||
'<p>My name: {{ myName }}</p>' +
|
||||
'<p>Friends:</p>' +
|
||||
'<ul>' +
|
||||
'<li *for="#name of names">' +
|
||||
'{{ name }}' +
|
||||
'</li>' +
|
||||
'</ul>' +
|
||||
'<p *if="names.length > 3">You have many friends!</p>',
|
||||
directives: [angular.For, angular.If]
|
||||
})
|
||||
];
|
||||
pre.prettyprint.lang-typescript
|
||||
code.
|
||||
//TypeScript
|
||||
import {Component, View, bootstrap, For, If} from 'angular2/angular2';
|
||||
@Component({
|
||||
selector: 'display'
|
||||
})
|
||||
@View({
|
||||
template: `
|
||||
<p>My name: {{ myName }}</p>
|
||||
<p>Friends:</p>
|
||||
<ul>
|
||||
<li *for="#name of names">
|
||||
{{ name }}
|
||||
</li>
|
||||
</ul>
|
||||
<p *if="names.length > 3">You have many friends!</p>
|
||||
`,
|
||||
directives: [For, If]
|
||||
})
|
||||
class DisplayComponent {
|
||||
myName: string;
|
||||
todos: Array<string>;
|
||||
constructor() {
|
||||
this.myName = "Alice";
|
||||
this.names = ["Aarav", "Martín", "Shannon", "Ariana", "Kai"];
|
||||
}
|
||||
}
|
||||
h2#Create-a-class Create a class for the array property and inject into component
|
||||
p.
|
||||
Before we get too much further, we should mention that putting our model (array) directly in our controller isn't
|
||||
proper form. We should separate the concerns by having another class serve the role of model and inject it into
|
||||
the controller.
|
||||
|
||||
p.
|
||||
Make a <code>FriendsService</code> class to provide the model with the list of friends. We'll put this in a new
|
||||
<code>friends_service.dart</code> under <code>web/</code>, and add <code>part friends_service.dart</code>
|
||||
to <code>main.dart</code>. Here's what the class looks like:
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
part of displaying_data;
|
||||
|
||||
class FriendsService {
|
||||
List<String> friendNames = ['Aarav', 'Martín', 'Shannon', 'Ariana', 'Kai'];
|
||||
}
|
||||
|
||||
p.
|
||||
Replace the current list of friends in DisplayComponent by passing in the FriendsService and setting the list of
|
||||
names in DisplayComponent to the names provided by the service you passed in.
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
DisplayComponent(FriendsService friendsService) {
|
||||
friendNames = friendsService.names;
|
||||
}
|
||||
p And then make FriendsService available to dependency injection
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
part of displaying_data;
|
||||
|
||||
@Component(
|
||||
selector: 'display',
|
||||
injectables: const[FriendsService]
|
||||
)
|
||||
@View(
|
||||
template: '''
|
||||
<p>My name: {{ myName }}</p>
|
||||
<p>Friends:</p>
|
||||
<ul>
|
||||
<li *for="#name of friendNames">
|
||||
{{ name }}
|
||||
</li>
|
||||
</ul>
|
||||
''',
|
||||
directives: const[For]
|
||||
)
|
||||
|
||||
class DisplayComponent {
|
||||
String myName = 'Alice';
|
||||
List<String> friendNames;
|
||||
|
||||
DisplayComponent(FriendsService friendsService) {
|
||||
friendNames = friendsService.names;
|
||||
}
|
||||
}
|
||||
|
||||
.l-main-section
|
||||
h2#Conditionally-displaying-data-with-If Conditionally displaying data with If
|
||||
p.
|
||||
Lastly, before we move on, let's handle showing parts of our UI conditionally with <code>If</code>. The
|
||||
<code>If</code> directive adds or removes elements from the DOM based on the expression you provide.
|
||||
|
||||
p See it in action by adding a paragraph at the end of your template
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<p *if="names.length > 3">You have many friends!</p>
|
||||
|
||||
p You'll also need to add the If directive so Angular knows to include it.
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
directives: const[For, If]
|
||||
p.
|
||||
As there are currently 5 items it the list, you'll see the message congratulating you on your many friends.
|
||||
Remove two items from the list, reload your browser, and see that the message no longer displays.
|
||||
|
||||
p Here's our final <code>show_properties.dart</code>
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
part of displaying_data;
|
||||
|
||||
@Component(
|
||||
selector: 'display',
|
||||
injectables: const[FriendsService]
|
||||
)
|
||||
@View(
|
||||
template: '''
|
||||
<p>My name: {{ myName }}</p>
|
||||
<p>Friends:</p>
|
||||
<ul>
|
||||
<li *for="#name of friendNames">
|
||||
{{ name }}
|
||||
</li>
|
||||
</ul>
|
||||
<p *if="friendNames.length > 3">You have many friends!</p>
|
||||
''',
|
||||
directives: const[For, If]
|
||||
)
|
||||
class DisplayComponent {
|
||||
String myName = 'Alice';
|
||||
List<String> friendNames;
|
||||
DisplayComponent(FriendsService friendsService) {
|
||||
friendNames = friendsService.names;
|
||||
}
|
||||
}
|
||||
|
||||
p And the accompanying <code>main.dart</code>:
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
library displaying_data;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:angular2/angular2.dart';
|
||||
import 'package:angular2/src/reflection/reflection.dart' show reflector;
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart' show ReflectionCapabilities;
|
||||
|
||||
part 'show_properties.dart';
|
||||
part 'friends_service.dart';
|
||||
|
||||
main() {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
bootstrap(DisplayComponent);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
.l-main-section
|
||||
p.
|
||||
As mentioned earlier, you build Angular applications as a tree of nested components. You've seen how to create
|
||||
a top-level component. You add child components to a parent component by using them in the parent component's
|
||||
template.
|
||||
p.
|
||||
Given a bootstrapping template with a <code><parent></code> tag in the body, you can create a parent
|
||||
component that uses a <code><child></code> component like so:
|
||||
|
||||
pre.prettyprint.linenums.lang-dart
|
||||
code.
|
||||
part of making_components;
|
||||
|
||||
@Component(
|
||||
selector: 'parent'
|
||||
)
|
||||
@View(
|
||||
template: '''
|
||||
<h1>{{ message }}</h1>
|
||||
<child></child>
|
||||
''',
|
||||
directives: const[ChildComponent]
|
||||
)
|
||||
class ParentComponent {
|
||||
String message = "I'm the parent";
|
||||
}
|
||||
|
||||
p You then just need to write the <code>ChildComponent</code> class to make it work:
|
||||
|
||||
pre.prettyprint.linenums.lang-dart
|
||||
code.
|
||||
part of making_components;
|
||||
|
||||
@Component(
|
||||
selector: 'child'
|
||||
)
|
||||
@View(
|
||||
template: '''
|
||||
<p> {{ message }} </p>
|
||||
'''
|
||||
)
|
||||
class ChildComponent {
|
||||
String message = "I'm the child";
|
||||
}
|
||||
|
||||
p.
|
||||
Notice that in addition to using the <code><child></code> element in the parent template, you also need to
|
||||
add <code>ChildComponent</code> in <code>ParentComponent</code>'s list of directives
|
||||
p.
|
||||
[TODO: Motivate communication between components with iterator example that passes index to the child]
|
|
@ -30,7 +30,7 @@
|
|||
.l-main-section
|
||||
h2#section-create-an-entry-point Create an entry point
|
||||
p.
|
||||
In the <code>web/</code> directory for you app, create an <code>index.html</code> file and add the Angular library
|
||||
In the <code>web/</code> directory for your app, create an <code>index.html</code> file and add the Angular library
|
||||
tags and a <code>main.dart</code> file where you'll build your first component.
|
||||
|
||||
p.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,137 @@
|
|||
.l-main-section
|
||||
p.
|
||||
You can make your application respond to user input by associating events with functions in your controller
|
||||
using the event syntax using <strong>()</strong> to surround the name of an event.
|
||||
p.
|
||||
For a particular control like an input you can have it call methods on your controller on keyup event like so:
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<input (keyup)="myControllerMethod()">
|
||||
p.
|
||||
As in previous examples, you can make element references available to other parts of the template as a local
|
||||
variable using the # syntax. With this and events, we can do the old "update text as you type" example:
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<input #my-name (keyup)>
|
||||
<p>{{my-name.value}}</p>
|
||||
|
||||
p.text-body(ng-non-bindable).
|
||||
The <code>#my-name</code> creates a local variable in the template that we'll refer to below in the
|
||||
<code><p></code> element. The <code>(keyup)</code> tells Angular to trigger updates when it gets a keyup
|
||||
event. And the <code>{{my-name.value}}</code> binds the text node of the <code><p></code> element to the
|
||||
input's value property.
|
||||
p Let's do something a little more complex where users enter items and add them to a list like this:
|
||||
div(align='center')
|
||||
img(src='user-input-example1.png')
|
||||
|
||||
|
||||
.l-main-section
|
||||
h2#section-create-an-array-property Create an array property
|
||||
p.
|
||||
With the default bootstrapping in place, create a TodoController class that will manage interactions with the
|
||||
list. Inside TodoController, add an array with an initial list of items. Then add a method that pushes new items
|
||||
on the array when called.
|
||||
|
||||
pre.prettyprint.linenums.lang-dart
|
||||
code.
|
||||
class TodoList {
|
||||
List<String> todos =
|
||||
['Eat breakfast', 'Walk dog', 'Breathe', 'Learn Angular'];
|
||||
|
||||
addTodo(String todo) {
|
||||
todos.add(todo);
|
||||
}
|
||||
|
||||
.callout.is-helpful
|
||||
header Production Best Practice
|
||||
p.
|
||||
As with the previous example, in a production application you will separate your model out into another class
|
||||
and inject it into <code>TodoController</code>. We've omitted it here for brevity.
|
||||
|
||||
.l-main-section
|
||||
h2#section-display-the-list-of-todos Display the list of todos
|
||||
p.
|
||||
Using the <code>*for</code> iterator, create an <code><li></code> for each item in the todos array and set
|
||||
its text to the value.
|
||||
|
||||
pre.prettyprint.linenums.lang-html
|
||||
code.
|
||||
<ul>
|
||||
<li *for="#todo of todos">
|
||||
{{ todo }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
.l-main-section
|
||||
h2#section-add-todos-to-the-list Add todos to the list via button click
|
||||
p.
|
||||
Now, add a text input and a button for users to add items to the list. As you saw above, you can create a local
|
||||
variable reference in your template with <code>#varname</code>. Call it <code>#todotext</code> here.
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<input #todotext>
|
||||
p.
|
||||
Lastly, specify the target of the click event binding as your controller's <code>addTodo()</code> method and pass
|
||||
it the value. Since you created a reference called <code>todotext</code>, you can get the value with
|
||||
<code>todotext.value.</code>
|
||||
|
||||
pre.prettyprint.lang-html
|
||||
code.
|
||||
<button (click)="addTodo(todotext.value)">Add Todo</button>
|
||||
|
||||
p And then create the doneTyping() method on TodoList and handle adding the todo text.
|
||||
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
doneTyping(KeyboardEvent event) {
|
||||
if (event.which == 13) {
|
||||
InputElement e = event.target;
|
||||
addTodo(e.value);
|
||||
e.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
.l-main-section
|
||||
h2#section-final-code Final Code
|
||||
p Here's the final <code>todo_list.dart</code>
|
||||
pre.prettyprint.lang-dart
|
||||
code.
|
||||
part of user_input;
|
||||
|
||||
@Component(
|
||||
selector: 'todo-list'
|
||||
)
|
||||
@View(
|
||||
// Without r before ''' (a raw string), $event breaks Angular!
|
||||
// An alternative is to use \$event instead.
|
||||
template: '''
|
||||
<ul>
|
||||
<li *for="#todo of todos">
|
||||
{{ todo }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<input #todotext (keyup)="doneTyping($event)">
|
||||
<button (click)="addTodo(todotext.value)">Add Todo</button>
|
||||
''',
|
||||
directives: const[For]
|
||||
)
|
||||
class TodoList {
|
||||
List<String> todos =
|
||||
['Eat breakfast', 'Walk dog', 'Breathe', 'Learn Angular'];
|
||||
|
||||
addTodo(String todo) {
|
||||
todos.add(todo);
|
||||
}
|
||||
|
||||
doneTyping(KeyboardEvent event) {
|
||||
if (event.which == 13) {
|
||||
InputElement e = event.target;
|
||||
addTodo(e.value);
|
||||
e.value = null;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue