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