444 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			444 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
.l-main-section
 | 
						|
  p.
 | 
						|
      Let's walk through how to display a property and a list of properties,
 | 
						|
      and then to conditionally show content
 | 
						|
      based on state. The final UI looks like this:
 | 
						|
 | 
						|
  figure.image-display
 | 
						|
    img(src='displaying-data-example1.png')
 | 
						|
 | 
						|
.l-main-section
 | 
						|
  h2#section-create-an-entry-point Create entry points and pubspec
 | 
						|
 | 
						|
  p.
 | 
						|
    Open your favorite editor and create a directory with
 | 
						|
    a <code>web/main.dart</code> file,
 | 
						|
    a <code>web/index.html</code> file, and
 | 
						|
    a <code>pubspec.yaml</code> file:
 | 
						|
 | 
						|
  .code-box
 | 
						|
    pre.prettyprint.lang-dart(data-name="dart")
 | 
						|
      code.
 | 
						|
        // web/main.dart
 | 
						|
        library displaying_data;
 | 
						|
 | 
						|
        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';
 | 
						|
 | 
						|
        main() {
 | 
						|
          reflector.reflectionCapabilities = new ReflectionCapabilities();
 | 
						|
          bootstrap(DisplayComponent);
 | 
						|
        }
 | 
						|
    pre.prettyprint.lang-html(data-name="html")
 | 
						|
      code.
 | 
						|
        <!-- web/index.html -->
 | 
						|
        <!DOCTYPE html>
 | 
						|
        <html>
 | 
						|
          <head>
 | 
						|
            <link rel="stylesheet" href="style.css">
 | 
						|
          </head>
 | 
						|
          <body>
 | 
						|
 | 
						|
            <display></display>
 | 
						|
 | 
						|
            <script type="application/dart" src="main.dart"></script>
 | 
						|
            <script src="packages/browser/dart.js"></script>
 | 
						|
          </body>
 | 
						|
        </html>
 | 
						|
    pre.prettyprint.lang-yaml(data-name="yaml")
 | 
						|
      code.
 | 
						|
        # pubspec.yaml
 | 
						|
        name: displaying_data
 | 
						|
        description: Dart version of Angular 2 example, Displaying Data
 | 
						|
        version: 0.0.1
 | 
						|
        dependencies:
 | 
						|
          angular2: 2.0.0-alpha.21
 | 
						|
          browser: any
 | 
						|
 | 
						|
  p.
 | 
						|
   All of this code should look familiar from the previous page,
 | 
						|
   except for the <code>library</code> and <code>part</code> statements
 | 
						|
   in <code>main.dart</code>.
 | 
						|
   Those statements let you implement part of the app in a different Dart file.
 | 
						|
   All three of these files remain similar in the rest of the examples,
 | 
						|
   so we'll just focus on what's different.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
  h2#section-showing-properties-with-interpolation Showing properties with interpolation
 | 
						|
  p.
 | 
						|
    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 a Dart file under <code>web</code>
 | 
						|
    named <code>show_properties.dart</code>,
 | 
						|
    and add the following:
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      // web/show_properties.dart
 | 
						|
      part of displaying_data;
 | 
						|
 | 
						|
      @Component(
 | 
						|
        selector: 'display'
 | 
						|
      )
 | 
						|
      @View(
 | 
						|
        template: '''
 | 
						|
      <p>My name: {{ myName }}</p>
 | 
						|
      '''
 | 
						|
      )
 | 
						|
      class DisplayComponent {
 | 
						|
        String myName = 'Alice';
 | 
						|
      }
 | 
						|
 | 
						|
  p.
 | 
						|
    You've just defined a component that encompasses a view and controller for the app. The view
 | 
						|
    defines a template:
 | 
						|
 | 
						|
  pre.prettyprint.lang-html
 | 
						|
    code.
 | 
						|
      <p>My name: {{ myName }}</p>
 | 
						|
 | 
						|
  p.
 | 
						|
   Angular will automatically pull the value of <code>myName</code> and
 | 
						|
   insert it into the browser,
 | 
						|
   automatically updating it whenever it changes.
 | 
						|
 | 
						|
  .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.
 | 
						|
   One thing to notice is that although you've written
 | 
						|
   your <code>DisplayComponent</code> class, you haven't
 | 
						|
   used <code>new</code> to instantiate it.
 | 
						|
   Because your class is associated with <code><display></code> elements in
 | 
						|
   the DOM, Angular automatically calls <code>new</code> 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 <code>DisplayComponent</code>, which has
 | 
						|
   just one property, <code>myName</code>.
 | 
						|
 | 
						|
  p.
 | 
						|
    Add a second line to the template,
 | 
						|
    so you can see Angular dynamically update content:
 | 
						|
 | 
						|
  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 app, and you'll now see the seconds updating automatically.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
  h2#Create-an-array Display an iterable using *for
 | 
						|
  p Moving up from a single value, create a property that's a list of values.
 | 
						|
 | 
						|
  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 list in your template with the <code>for</code> directive to create copies of DOM elements
 | 
						|
    with one for each item in the list.
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      @View(
 | 
						|
        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 <code>For</code> directive used by
 | 
						|
    the template to <code>show_properties.dart</code>, so that Angular knows to include it.
 | 
						|
    Add <code>For</code> using the optional <code>directives</code> parameter,
 | 
						|
    which contains a list of directives:
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      @View(
 | 
						|
        template: '''
 | 
						|
      // ...HTML...
 | 
						|
        ''',
 | 
						|
        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>
 | 
						|
       such as a list.
 | 
						|
    li <code>#name</code>: Refer to individual values of the iterable as <code>name</code>.
 | 
						|
    li <code>of friendNames</code>: The iterable to use is called <code>friendNames</code> 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 model and inject it
 | 
						|
  p.
 | 
						|
    Before we get too much further, we should mention that putting the model (list) directly into the 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 implement a model containing a list of friends. We'll put this in a new
 | 
						|
    <code>friends_service.dart</code> under <code>web/</code>. Here's what the class looks like:
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      // web/friends_service.dart
 | 
						|
      part of displaying_data;
 | 
						|
 | 
						|
      class FriendsService {
 | 
						|
        List<String> friendNames = ['Aarav', 'Martín', 'Shannon', 'Ariana', 'Kai'];
 | 
						|
      }
 | 
						|
 | 
						|
  .callout.is-helpful
 | 
						|
    header Note
 | 
						|
    p.
 | 
						|
      Remember to tie <code>friends_service.dart</code> into the library's main file:
 | 
						|
      add <code>part friends_service.dart</code> to <code>main.dart</code>.
 | 
						|
  p.
 | 
						|
    Now you can replace the current list of friends in DisplayComponent.
 | 
						|
    First add a FriendsService parameter to the constructor.
 | 
						|
    Then set <code>friendNames</code> to the names provided by the service.
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      // In web/show_properties.dart
 | 
						|
      class DisplayComponent {
 | 
						|
        String myName = 'Alice';
 | 
						|
        List<String> friendNames;
 | 
						|
 | 
						|
        DisplayComponent(FriendsService friendsService) {
 | 
						|
          friendNames = friendsService.names;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
  p.
 | 
						|
    Next, make FriendsService available to dependency injection
 | 
						|
    by adding an <code>injectables</code> parameter to DisplayComponent's
 | 
						|
    <code>@Component</code> annotation:
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
      code.
 | 
						|
        @Component(
 | 
						|
          selector: 'display',
 | 
						|
          injectables: const[FriendsService]
 | 
						|
        )
 | 
						|
 | 
						|
.l-main-section
 | 
						|
  h2#Conditionally-displaying-data-with-If Conditionally display data using *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.
 | 
						|
    Also add <code>If</code> to the list of directives,
 | 
						|
    so Angular knows to include it:
 | 
						|
 | 
						|
  pre.prettyprint.lang-dart
 | 
						|
    code.
 | 
						|
      directives: const[For, If]
 | 
						|
  p.
 | 
						|
    The list current has 5 items, so if you run the app 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.
 | 
						|
    <!-- PENDING: mention somewhere that once you start a web server,
 | 
						|
    you can just refresh the browser to see your changes. -->
 | 
						|
 | 
						|
  p Here's the final code.
 | 
						|
 | 
						|
  .code-box
 | 
						|
    pre.prettyprint.lang-dart(data-name="show_properties.dart")
 | 
						|
      code.
 | 
						|
        // web/show_properties.dart
 | 
						|
        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;
 | 
						|
          }
 | 
						|
        }
 | 
						|
    pre.prettyprint.lang-dart(data-name="friends_service.dart")
 | 
						|
      code.
 | 
						|
        // web/friends_service.dart
 | 
						|
        part of displaying_data;
 | 
						|
 | 
						|
        class FriendsService {
 | 
						|
          List<String> names = ['Aarav', 'Martín', 'Shannon', 'Ariana', 'Kai'];
 | 
						|
        }
 | 
						|
    pre.prettyprint.lang-dart(data-name="main.dart")
 | 
						|
      code.
 | 
						|
        // web/main.dart
 | 
						|
        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);
 | 
						|
        }
 | 
						|
    pre.prettyprint.lang-html(data-name="html")
 | 
						|
      code.
 | 
						|
        <!-- web/index.html -->
 | 
						|
        <!DOCTYPE html>
 | 
						|
        <html>
 | 
						|
          <head>
 | 
						|
            <link rel="stylesheet" href="style.css">
 | 
						|
          </head>
 | 
						|
          <body>
 | 
						|
 | 
						|
            <display></display>
 | 
						|
 | 
						|
            <script type="application/dart" src="main.dart"></script>
 | 
						|
            <script src="packages/browser/dart.js"></script>
 | 
						|
          </body>
 | 
						|
        </html>
 | 
						|
    pre.prettyprint.lang-yaml(data-name="yaml")
 | 
						|
      code.
 | 
						|
        # pubspec.yaml
 | 
						|
        name: displaying_data
 | 
						|
        description: Dart version of Angular 2 example, Displaying Data
 | 
						|
        version: 0.0.1
 | 
						|
        dependencies:
 | 
						|
          angular2: 2.0.0-alpha.21
 | 
						|
          browser: any
 | 
						|
.l-main-section
 | 
						|
  h2#section-explanations Explanations
 | 
						|
 | 
						|
  .l-sub-section
 | 
						|
    h3 Using multiple Dart files in an Angular app
 | 
						|
 | 
						|
      p.
 | 
						|
        Dart offers a few ways to implement an app in multiple files.
 | 
						|
        In this guide, all the code for each example is in a single library;
 | 
						|
        each Dart file under <code>web</code> is part of that library.
 | 
						|
 | 
						|
      p.
 | 
						|
        To let the code in <code>main.dart</code>
 | 
						|
        use the code in <code>show_properties.dart</code>,
 | 
						|
        declare a library in <code>main.dart</code>.
 | 
						|
        Then make <code>show_properties.dart</code> part of that library.
 | 
						|
 | 
						|
      .code-box
 | 
						|
        pre.prettyprint.lang-dart(data-name="main library file")
 | 
						|
          code.
 | 
						|
            // web/main.dart
 | 
						|
            library displaying_data;
 | 
						|
            // imports...
 | 
						|
            part 'show_properties.dart';
 | 
						|
            // Code goes here...
 | 
						|
        pre.prettyprint.lang-dart(data-name="additional library file")
 | 
						|
          code.
 | 
						|
            // web/show_properties.dart
 | 
						|
            part of displaying_data;
 | 
						|
            // Code goes here...
 | 
						|
 | 
						|
      p.
 | 
						|
        Another way to split Dart code is to
 | 
						|
        define multiple libraries in a single package.
 | 
						|
        The additional libraries go under a <code>lib</code> directory
 | 
						|
        parallel to <code>web</code>.
 | 
						|
        <!-- PENDING: show or point to an example -->
 | 
						|
 | 
						|
      p.
 | 
						|
        Yet another approach, often used when some of the code is highly reusable,
 | 
						|
        is to split the code into libraries in two or more packages.
 | 
						|
 | 
						|
      p.
 | 
						|
        For more information on implementing Dart libraries, see
 | 
						|
        <a href="https://www.dartlang.org/docs/dart-up-and-running/ch02.html#libraries-and-visibility">Libraries and visibility</a>
 | 
						|
        in the
 | 
						|
        <a href="https://www.dartlang.org/docs/dart-up-and-running/ch02.html">Dart language tour</a>.
 |