| OLD | NEW |
| (Empty) | |
| 1 polymer_expressions |
| 2 =================== |
| 3 |
| 4 Polymer Expressions are an expressive syntax that can be used in templates in |
| 5 Dart. Polymer Expressions allow you to write complex binding expressions, with |
| 6 property access, function invocation, list/map indexing, and two-way filtering |
| 7 like: |
| 8 |
| 9 ```html |
| 10 {{ person.title + " " + person.getFullName() | upppercase }} |
| 11 ``` |
| 12 |
| 13 ## Overview |
| 14 |
| 15 ### Model-Driven Views (MDV) |
| 16 [MDV][mdv] allows you to define templates directly in HTML that are rendered by
the |
| 17 browser into the DOM. Templates are bound to a data model, and changes to the |
| 18 data are automatically reflected in the DOM, and changes in HTML inputs are |
| 19 assigned back into the model. The template and model are bound together via |
| 20 binding expressions that are evaluated against the model. These binding |
| 21 expressions are placed in double-curly-braces, or "mustaches". |
| 22 |
| 23 Example: |
| 24 |
| 25 ```html |
| 26 <template> |
| 27 <p>Hello {{ person.name }}</p> |
| 28 </template> |
| 29 ``` |
| 30 |
| 31 MDV includes a very basic binding syntax which only allows a series of |
| 32 dot-separate property names. |
| 33 |
| 34 [mdv]: http://www.polymer-project.org/platform/mdv.html |
| 35 |
| 36 ### Custom Binding Syntaxes with BindingDelegate |
| 37 |
| 38 While MDV's built-in syntax is very basic, it does allow custom syntaxes called |
| 39 "binding delegates" to be installed and used. A binding delegate can interpret |
| 40 the contents of mustaches however it likes. PolymerExpressions is such a |
| 41 binding delegate. |
| 42 |
| 43 Example: |
| 44 |
| 45 ```html |
| 46 <template bind> |
| 47 <p>Hello {{ person.title + " " + person.getFullName() | uppercase }}</p> |
| 48 </template> |
| 49 ``` |
| 50 |
| 51 ## Usage |
| 52 |
| 53 ### Installing from Pub |
| 54 |
| 55 Add the following to your pubspec.yaml file: |
| 56 |
| 57 ```yaml |
| 58 dependencies: |
| 59 polymer_expressions: any |
| 60 ``` |
| 61 |
| 62 Hint: check https://pub.dartlang.org/packages/polymer_expressions for the latest |
| 63 version number. |
| 64 |
| 65 Then import polymer_expressions.dart: |
| 66 |
| 67 import 'package:polymer_expressions/polymer_expressions.dart'; |
| 68 |
| 69 ### Registering a Binding Delegate |
| 70 |
| 71 **Polymer Expressions are now the default syntax for `<polymer-element>` custom |
| 72 elements.** |
| 73 |
| 74 You do not need to manually register the bindingDelegate if your bindings are |
| 75 inside a custom element. However, if you want to use polymer_expressions outside |
| 76 a custom element, read on: |
| 77 |
| 78 Binding delegates must be installed on a template before they can be used. |
| 79 For example, set the bindingDelegate property of your template |
| 80 elements to an instance of PolymerExpressions. The templates will then use the |
| 81 PolymerExpressions instance to interpret |
| 82 binding expressions. |
| 83 |
| 84 ```dart |
| 85 import 'dart:html'; |
| 86 import 'package:polymer_expressions/polymer_expressions.dart'; |
| 87 |
| 88 main() { |
| 89 var template = query('#my_template'); |
| 90 template.bindingDelegate = new PolymerExpressions(); |
| 91 } |
| 92 ``` |
| 93 |
| 94 ### Registering Top-Level Variables |
| 95 |
| 96 Before a top-level variable can be used, it must be registered. The |
| 97 PolymerExpressions constructor takes a map of named values to use as variables. |
| 98 |
| 99 ```dart |
| 100 main() { |
| 101 var globals = { |
| 102 'uppercase': (String v) => v.toUpperCase(), |
| 103 'app_id': 'my_app_123', |
| 104 }; |
| 105 var template = query('#my_template'); |
| 106 template.bindingDelegate = new PolymerExpressions(globals: globals); |
| 107 } |
| 108 ``` |
| 109 |
| 110 ## Features |
| 111 |
| 112 ### The Model and Scope |
| 113 |
| 114 Polymer Expressions allow binding to more than just the model assigned to a |
| 115 template instance. Top-level variables can be defined so that you can use |
| 116 filters, global variables and constants, functions, etc. These variables and the |
| 117 model are held together in a container called a Scope. Scopes can be nested, |
| 118 which happens when template tags are nested. |
| 119 |
| 120 ### Two-way Bindings |
| 121 |
| 122 Bindings can be used to modify the data model based on events in the DOM. The |
| 123 most common case is to bind an <input> element's value field to a model |
| 124 property and have the property update when the input changes. For this to work, |
| 125 the binding expression must be "assignable". Only a subset of expressions are |
| 126 assignable. Assignable expressions cannot contain function calls, operators, and |
| 127 any index operator must have a literal argument. Assignable expressions can |
| 128 contain filter operators as long as all the filters are two-way transformers. |
| 129 |
| 130 Some restrictions may be relaxed further as allowed. |
| 131 |
| 132 Assignable Expressions: |
| 133 |
| 134 * `foo` |
| 135 * `foo.bar` |
| 136 * `items[0].description` |
| 137 * `people['john'].name` |
| 138 * `product.cost | convertCurrency('ZWD')` where `convertCurrency` evaluates to |
| 139 a Tranformer object. |
| 140 |
| 141 Non-Assignable Expressions: |
| 142 |
| 143 * `a + 1` |
| 144 * `!c` |
| 145 * `foo()` |
| 146 * `person.lastName | uppercase` where `uppercase` is a filter function. |
| 147 |
| 148 ### Null-Safety |
| 149 |
| 150 Expressions are generally null-safe. If an intermediate expression yields `null` |
| 151 the entire expression will return null, rather than throwing an exception. |
| 152 Property access, method invocation and operators are null-safe. Passing null to |
| 153 a function that doesn't handle null will not be null safe. |
| 154 |
| 155 ### Streams |
| 156 |
| 157 Polymer Expressions have experimental support for binding to streams, and when |
| 158 new values are passed to the stream, the template updates. The feature is not |
| 159 fully implemented yet. |
| 160 |
| 161 See the examples in /example/streams for more details. |
| 162 |
| 163 ## Syntax |
| 164 |
| 165 ### Property Access |
| 166 |
| 167 Properties on the model and in the scope are looked up via simple property |
| 168 names, like `foo`. Property names are looked up first in the top-level |
| 169 variables, next in the model, then recursively in parent scopes. Properties on |
| 170 objects can be access with dot notation like `foo.bar`. |
| 171 |
| 172 The keyword `this` always refers to the model if there is one, otherwise `this` |
| 173 is `null`. If you have model properties and top-level variables with the same |
| 174 name, you can use `this` to refer to the model property. |
| 175 |
| 176 ### Literals |
| 177 |
| 178 Polymer Expressions support number, boolean, string, and map literals. Strings |
| 179 can use either single or double quotes. |
| 180 |
| 181 * Numbers: `1`, `1.0` |
| 182 * Booleans: `true`, `false` |
| 183 * Strings: `'abc'`, `"xyz"` |
| 184 * Maps: `{ 'a': 1, 'b': 2 }` |
| 185 |
| 186 List literals are planned, see [issue 9](https://github.com/dart-lang/polymer_ex
pressions/issues/9) |
| 187 |
| 188 ### Functions and Methods |
| 189 |
| 190 If a property is a function in the scope, a method on the model, or a method on |
| 191 an object, it can be invoked with standard function syntax. Functions and |
| 192 Methods can take arguments. Named arguments are not supported. Arguments can be |
| 193 literals or variables. |
| 194 |
| 195 Examples: |
| 196 |
| 197 * Top-level function: `myFunction()` |
| 198 * Top-level function with arguments: `myFunction(a, b, 42)` |
| 199 * Model method: `aMethod()` |
| 200 * Method on nested-property: `a.b.anotherMethod()` |
| 201 |
| 202 ### Operators |
| 203 |
| 204 Polymer Expressions supports the following binary and unary operators: |
| 205 |
| 206 * Arithmetic operators: +, -, *, /, %, unary + and - |
| 207 * Comparison operators: ==, !=, <=, <, >, >= |
| 208 * Boolean operators: &&, ||, unary ! |
| 209 |
| 210 Expressions do not support bitwise operators such as &, |, << and >>, or increme
nt/decrement operators (++ and --) |
| 211 |
| 212 ### List and Map Indexing |
| 213 |
| 214 List and Map like objects can be accessed via the index operator: [] |
| 215 |
| 216 Examples: |
| 217 |
| 218 * `items[2]` |
| 219 * `people['john']` |
| 220 |
| 221 Unlike JavaScript, list and map contents are not generally available via |
| 222 property access. That is, the previous examples are not equivalent to `items.2` |
| 223 and `people.john`. This ensures that access to properties and methods on Lists |
| 224 and Maps is preserved. |
| 225 |
| 226 ### Filters and Transformers |
| 227 |
| 228 A filter is a function that transforms a value into another, used via the pipe |
| 229 syntax: `value | filter` Any function that takes exactly one argument can be |
| 230 used as a filter. |
| 231 |
| 232 Example: |
| 233 |
| 234 If `person.name` is "John", and a top-level function named `uppercase` has been |
| 235 registered, then `person.name | uppercase` will have the value "JOHN". |
| 236 |
| 237 The pipe syntax is used rather than a regular function call so that we can |
| 238 support two-way bindings through transformers. A transformer is a filter that |
| 239 has an inverse function. Transformers must extend or implement the `Transformer` |
| 240 class, which has `forward()` and `reverse()` methods. |
| 241 |
| 242 ### Repeating Templates |
| 243 |
| 244 A template can be repeated by using the "repeat" attribute with a binding. The |
| 245 binding can either evaluate to an Iterable, in which case the template is |
| 246 instantiated for each item in the iterable and the model of the instance is |
| 247 set to the item, or the binding can be a "in" iterator expression, in which |
| 248 case a new variable is added to each scope. |
| 249 |
| 250 The following examples produce the same output. |
| 251 |
| 252 Evaluate to an iterable: |
| 253 |
| 254 ```html |
| 255 <template repeat="{{ items }}"> |
| 256 <div>{{ }}</div> |
| 257 </template> |
| 258 ``` |
| 259 |
| 260 "in" expression: |
| 261 |
| 262 ```html |
| 263 <template repeat="{{ item in items }}"> |
| 264 <div>{{ item }}</div> |
| 265 </template> |
| 266 ``` |
| 267 |
| 268 ## Status |
| 269 |
| 270 The syntax implemented is experimental and subject to change, in fact, it |
| 271 **will** change soon. The goal is to be compatible with Polymer's binding |
| 272 syntax. We will announce breaking changes on the |
| 273 [web-ui@dartlang.org mailing list][web-ui-list]. |
| 274 |
| 275 Please [file issues on Dart project page](http://dartbug.com/new) |
| 276 for any bugs you find or for feature requests. Make a note that it applies to |
| 277 "package:polymer_expressions" |
| 278 |
| 279 You can discuss Polymer Expressions on the |
| 280 [web-ui@dartlang.org mailing list][web-ui-list]. |
| 281 |
| 282 [web-ui-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/web-ui |
| OLD | NEW |