diff --git a/public/docs/dart/latest/_data.json b/public/docs/dart/latest/_data.json index 4982e87a15..10a40b3ff8 100644 --- a/public/docs/dart/latest/_data.json +++ b/public/docs/dart/latest/_data.json @@ -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 angulardart.org." }, - + "api": { "icon": "book", "title": "API Proposal" diff --git a/public/docs/dart/latest/guide/_data.json b/public/docs/dart/latest/guide/_data.json index 443462cdec..3fb2fc9384 100644 --- a/public/docs/dart/latest/guide/_data.json +++ b/public/docs/dart/latest/guide/_data.json @@ -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" } -} +} \ No newline at end of file diff --git a/public/docs/dart/latest/guide/displaying-data-example1.png b/public/docs/dart/latest/guide/displaying-data-example1.png new file mode 100644 index 0000000000..d0f02a6464 Binary files /dev/null and b/public/docs/dart/latest/guide/displaying-data-example1.png differ diff --git a/public/docs/dart/latest/guide/displaying-data.jade b/public/docs/dart/latest/guide/displaying-data.jade index 3513e5a7c1..185b1aed4f 100644 --- a/public/docs/dart/latest/guide/displaying-data.jade +++ b/public/docs/dart/latest/guide/displaying-data.jade @@ -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 <display> 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 show-properties.html file with the content: + pre.prettyprint.lang-html + code. + //show-properties.html + <display></display> + p + | The <display> 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 {{ }}. + 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 {{ }}. - p To see this working, create another file, show-properties.js, and add the following: + p To see this working, create another file, show-properties.dart, 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 myName 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 DisplayComponent 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 DisplayComponent 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 DisplayComponent 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 template: to specify an inline view, for larger templates you'd + want to move them to a separate file and load them with templateUrl: instead. - p. - Angular will automatically pull the value of myName 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 DisplayComponent 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 DisplayComponent 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 DisplayComponent that has - just one property, myName. - - .callout.is-helpful - header Note - p. - While you've used template: to specify an inline view, for larger templates you'd - want to move them to a separate file and load them with templateUrl: 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 DisplayComponent a starting value for time and a call to update time - via setInterval. - - 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 for 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 angular.For 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 DisplayComponent a starting value for time and a call to update time + via setInterval. + + 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. - *for : create a DOM element for each item in an - iterable - like an array - li #name : refer to individual values of the iterable as 'name' - li of names : 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 FriendsService 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 for 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 angular.For directive used by + the template to show_properties.dart 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. + *for : create a DOM element for each item in an + iterable + like an array + li #name : refer to individual values of the iterable as 'name' + li of friendNames : 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 If. The - If 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; - constructor() { - this.myName = "Alice"; - this.names = ["Aarav", "Martín", "Shannon", "Ariana", "Kai"]; - } - } \ No newline at end of file + 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 FriendsService class to provide the model with the list of friends. We'll put this in a new + friends_service.dart under web/, and add part friends_service.dart + to main.dart. 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 If. The + If 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 show_properties.dart + + 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 main.dart: + + 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); + } \ No newline at end of file diff --git a/public/docs/dart/latest/guide/making-components.jade b/public/docs/dart/latest/guide/making-components.jade new file mode 100644 index 0000000000..30d2235763 --- /dev/null +++ b/public/docs/dart/latest/guide/making-components.jade @@ -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 <parent> tag in the body, you can create a parent + component that uses a <child> 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 ChildComponent 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 <child> element in the parent template, you also need to + add ChildComponent in ParentComponent's list of directives + p. + [TODO: Motivate communication between components with iterator example that passes index to the child] diff --git a/public/docs/dart/latest/guide/setup.jade b/public/docs/dart/latest/guide/setup.jade index 329202fc0e..70d3aa4a81 100644 --- a/public/docs/dart/latest/guide/setup.jade +++ b/public/docs/dart/latest/guide/setup.jade @@ -30,7 +30,7 @@ .l-main-section h2#section-create-an-entry-point Create an entry point p. - In the web/ directory for you app, create an index.html file and add the Angular library + In the web/ directory for your app, create an index.html file and add the Angular library tags and a main.dart file where you'll build your first component. p. diff --git a/public/docs/dart/latest/guide/user-input-example1.png b/public/docs/dart/latest/guide/user-input-example1.png new file mode 100644 index 0000000000..91e2dcfed1 Binary files /dev/null and b/public/docs/dart/latest/guide/user-input-example1.png differ diff --git a/public/docs/dart/latest/guide/user-input.jade b/public/docs/dart/latest/guide/user-input.jade new file mode 100644 index 0000000000..db83a31230 --- /dev/null +++ b/public/docs/dart/latest/guide/user-input.jade @@ -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 () 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 #my-name creates a local variable in the template that we'll refer to below in the + <p> element. The (keyup) tells Angular to trigger updates when it gets a keyup + event. And the {{my-name.value}} binds the text node of the <p> 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 TodoController. 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 *for iterator, create an <li> 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 #varname. Call it #todotext here. + + pre.prettyprint.lang-html + code. + <input #todotext> + p. + Lastly, specify the target of the click event binding as your controller's addTodo() method and pass + it the value. Since you created a reference called todotext, you can get the value with + todotext.value. + + 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 todo_list.dart + 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; + } + } + } \ No newline at end of file