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 collectionThe 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:
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.
18.119.122.82