A book component in AngularDart

We already saw how to encapsulate a 3D book from Chapter 4, Developing a Mobile App with Dart, into a polymer.dart custom element. Now we'll do the same but in AngularDart now.

We can skip main.dart, because there's nothing new for us there, and see <body> in index.html:

<!-- web/index.html -->
<body>
  <p>angular: <input type="number" ng-model="elementsCount"></p>
  <shelf books-count="elementsCount"></shelf>

  <script type="application/dart" src="main.dart"></script>
</body>

Note that we're setting ng-model outside any component, so it'll be kept in the root scope, which is automatically set to <html>. Also, we're using <input type="number">, which tells AngularDart to convert the input from this field into an integer automatically.

The <shelf> element has one custom attribute called books-count, and we'll also use cssUrl to set a custom CSS file for this Shadow DOM:

// lib/component/shelf.dart
@Component(
    selector: 'shelf',
    templateUrl: 'shelf.html',
    cssUrl: 'shelf.css'
)
class ShelfComponent {
  @NgOneWay('books-count')
  int booksCount;
}

The shelf.html HMTL template is following:

<!-- lib/component/shelf.html -->
<h2>AngularDart</h2>
<div>
  <angular-book
      ng-repeat="book in booksCount | intToList"
      cover-image="{{ $even ? 'cover-old.jpg' : 'cover-new.jpg'}}"
      base-color="{{ $even ? '#000' : '#da944c'}}">
  </angular-book>
</div>

This time, we're using a custom formatter in the ng-repeat directive because ng-repeat can iterate only collections but booksCount is an integer that we'll use to create a List object with this number of items. Each iteration of ng-repeat creates a few local properties that might be useful:

  • $index: This is the index (offset) of a current item (0 … n – 1)
  • $even: This is true if this item is at an even index
  • $odd: This is true if this item is at an odd index
  • $first: This is true if this item is the first in the collection
  • $last: This is true if this item is the last in the collection
  • $middle: This is true if this item is neither the first nor the last item in the collection

The code for our custom formatter goes to int_to_list.dart:

// lib/formatter/int_to_list.dart
@Formatter(name: 'intToList')
class IntToListFormatter {
  List call(dynamic num) {
    int intValue;
    // Make sure the value is an integer.
    if (num is String) intValue = int.parse(num);
    intValue = (num == null ? 0 : num);
    
    return new List.filled(intValue, true);
  }
}

Just don't forget to include int_to_list.dart as a dependency among components in main.dart:

// web/main.dart
MyAppModule() {
  /* … */
  bind(IntToListFormatter);
}

The code for book elements is very simple as well. Note that we're not going to encapsulate them in the Shadow DOM because we already created one in ShelfComponent and we don't need another one:

// lib/component/book.dart
@Component(
    selector: 'angular-book',
    templateUrl: 'book.html',
    cssUrl: 'book.css',
    useShadowDom: false
)
class BookComponent {
  @NgAttr('cover-image')
  String coverImage;
  
  @NgAttr('base-color')
  String baseColor;
}

In the template, we can use the <angular-book> element itself as a wrapper for all the book's faces. The rest looks very similar to the template in the polymer.dart example:

<!-- lib/component/book.html -->
<div class="front" style="background-image: url(./{{coverImage}})">
</div>
<div class="left" style="background-color: {{baseColor}}"></div>
<div class="right"></div>
<div class="back" style="background-color: {{baseColor}}"></div>
<div class="top"></div>
<div class="bottom"></div>

We don't even need to include CSS files here, because it's basically what we already used in polymer.dart. Feel free to download the source code for this chapter if you have any hesitations or go back to the previous chapter.

Just remember that the :host CSS selector can be used to refer to the current custom element in both polymer.dart and AngularDart.

Finally, this is our result in the browser:

A book component in AngularDart

We wrapped both books in just one Shadow DOM. In polymer.dart, all elements have their Shadow DOM unless you extend the default PolymerElement class, copy children elements directly to the host element, and therefore, bypass the Shadow DOM. Frankly, this isn't recommended because it violates the main purpose of Polymer, but you might run into a situation where you really want to avoid using the Shadow DOM (like core-list for example). With AngularDart, this is made very simple by just setting one property.

By quickly comparing the same functionality implemented in polymer.dart and AngularDart, we can see that the one written in AngularDart is actually shorter.

AngularDart can, with a little effort, connect various parts of a web application together. It's intended to be a self-contained framework that solves logic, model, and presentation aspects of applications.

Polymer.dart is best for creating independent and reusable components that can be imported into any web page, regardless of the rest of the code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.122.82