There are two good ways to learn something new: flail around making dumb mistakes and reading smarter people's words and code. Naturally, I prefer the former.
In all seriousness, I find it easier to internalize how a language or tool wants me to work if I struggle to make it work the way I think it should. Usually I can learn a thing or two about my subject of study and I inevitably get exposed to smarter people's work while I figure out why my approach does not work. It might seems counter-intuitive, but really, making mistakes—the worse the better—really works well as I learn.
But tonight, I try the opposite. I have been working against Polymer long enough. It is time that I tried a trick of two that I have picked up along the way. I start with the “model pattern,” for lack of a better name. Actually a better name might simply be the strategy pattern because that is what it really is. But I keep calling it the model pattern when I come across others doing it in Polymer mostly because there is always a
model
attribute on the Polymer. I don't know why, but I find that real classy. I want to be classy too. And what's more classy that order pizza? So I am going to build an
<x-pizza>
element that can build a pizza for order.I start a new web application with a Dart Pub
pubspec.yaml
that pulls in Polymer.dart:name: model_example dependencies: polymer: any dev_dependencies: unittest: any transformers: - polymer: entry_points: web/index.htmlI start a pizza building homepage to smoke test my model pattern Polymer. I create it as
web/index.html
:<!DOCTYPE html> <html lang="en"> <head> <title>Pizza Maker</title> <!-- Load component(s) --> <link rel="import" href="packages/model_example/elements/x-pizza.html"> <!-- Load Polymer --> <script type="application/dart"> export 'package:polymer/init.dart'; </script> </head> <body> <div class="container"> <h1>Dart Bros. Pizza Builder</h1> <x-pizza></x-pizza> </div> </body> </html>That is almost boilerplate at this point. I pull in the Polymer definition and the Polymer.dart platform at top. Then I use the
<x-pizza>
element below.Similarly, the
<x-pizza>
definition is fairly straight-forward. I create lib/elements/x-pizza.html
as:<polymer-element name="x-pizza"> <template> <h2>Build Your Pizza</h2> <pre>{{pizzaState}}</pre> <p> <select class="form-control" value="{{currentFirstHalf}}"> <option>Choose an ingredient...</option> <option value="{{ingredient}}" template repeat="{{ingredient in ingredients}}"> {{ingredient}} </option> </select> <button on-click="{{addFirstHalf}}" type="button" class="btn btn-default"> Add First Half Topping </button> </p> <!-- ... --> </template> <script type="application/dart" src="x_pizza.dart"></script> </polymer-element>That is just variable binding in templates.
The bulk of the work comes in the backing class, which needs a Pizza class:
class Pizza { List<String> firstHalfToppings = []; List<String> secondHalfToppings = []; List<String> wholeToppings = []; toString()=> """First Half: $firstHalfToppings Second Half: $secondHalfToppings Whole: $wholeToppings"""; }To use that as a model, I need only define an instance variable cleverly named “model” and assign an instance of
Pizza
to it:@CustomTag('x-pizza') class XPizza extends PolymerElement { final bool applyAuthorStyles = true; final List ingredients = [ 'pepperoni', 'sausage', 'green peppers' ]; @observable String currentFirstHalf = 'Choose an ingredient...'; // ... @observable String pizzaState; Pizza model = new Pizza(); XPizza.created(): super.created(); }All that is needed at this point is to use the model, which I do in the various add-toppings bound methods:
@CustomTag('x-pizza') class XPizza extends PolymerElement { // ... addFirstHalf() { model.firstHalfToppings.add(currentFirstHalf); pizzaState = model.toString(); } // ... }And that does the trick:
That is not quite the end of the story, however. I should be able to make the model itself observable so that, when its internal state is updated, it can trigger the update to the value displayed to the hungry buyer. I will leave that for another day. For now, I am happy just being on the way to classiness.
Day #994
What, no choice in Pizza base :-P
ReplyDeleteNice. Thanks.
ReplyDelete