| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 --- | 
|  | 2 layout: default | 
|  | 3 title: "Polymer Elements" | 
|  | 4 description: "Use Polymer.dart to build better UIs with less code." | 
|  | 5 has-permalinks: true | 
|  | 6 tutorial: | 
|  | 7   id: polymer-intro | 
|  | 8 next: fetchdata | 
|  | 9 next-title: "Fetch Data Dynamically" | 
|  | 10 prev: custom-elements | 
|  | 11 prev-title: "Define a Custom DOM Tag" | 
|  | 12 --- | 
|  | 13 | 
|  | 14 {% capture whats_the_point %} | 
|  | 15 | 
|  | 16 * Polymer.dart is the next evolution of Web UI. | 
|  | 17 * Everything in Polymer.dart is an element. | 
|  | 18 * Use Polymer.dart to build custom tags. | 
|  | 19 * Bind Dart data to HTML elements. | 
|  | 20 * Declaratively bind event handlers to elements. | 
|  | 21 | 
|  | 22 {% endcapture %} | 
|  | 23 | 
|  | 24 {% capture sample_links %} | 
|  | 25 | 
|  | 26 <p> | 
|  | 27 Get the source code for the samples featured in this target:</p> | 
|  | 28 | 
|  | 29 <ul> | 
|  | 30   <li> | 
|  | 31     <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
     /target06-polymer/stopwatch" | 
|  | 32        target="_blank">stopwatch</a> | 
|  | 33   </li> | 
|  | 34 </ul> | 
|  | 35 | 
|  | 36 {% endcapture %} | 
|  | 37 | 
|  | 38 {% capture content %} | 
|  | 39 | 
|  | 40 <div class="tute-target-title"> | 
|  | 41 <h1>{{page.title}}</h1> | 
|  | 42 <h3>Create new DOM tags with Polymer elements</h3> | 
|  | 43 </div> | 
|  | 44 | 
|  | 45 <div id="under-construction" markdown="1"> | 
|  | 46 <h3> <i class="icon-wrench"> </i> Under construction </h3> | 
|  | 47 | 
|  | 48 This is a draft under construction. | 
|  | 49 Your kindly worded | 
|  | 50 <a | 
|  | 51  href="http://code.google.com/p/dart/issues/entry?template=Tutorial%20feedback" | 
|  | 52  target="_blank"> | 
|  | 53 comments and suggestions | 
|  | 54 </a> | 
|  | 55 are appreciated. | 
|  | 56 Thank you for your patience. | 
|  | 57 </div> | 
|  | 58 | 
|  | 59 Polymer elements are one feature of the | 
|  | 60 <a href="http://www.polymer-project.org/">Polymer</a> project, | 
|  | 61 whose primary aim is to help manage the complexity | 
|  | 62 of building web applications. | 
|  | 63 <a href="http://www.dartlang.org/polymer-dart/">Polymer.dart</a> | 
|  | 64 is the Dart implementation of Polymer. | 
|  | 65 | 
|  | 66 A Polymer element is a customized element you can define yourself, | 
|  | 67 encapsulating appearance and/or behavior within semantically meaningful DOM tags
     . | 
|  | 68 | 
|  | 69 * [An example](#an-example) | 
|  | 70 * [Installing Polymer.dart](#getting-polymer-dart) | 
|  | 71 * [Including Polymer.dart in your application](#bootstrap) | 
|  | 72 * [Instantiating a Polymer element](#instantiating) | 
|  | 73 * [Defining a Polymer element](#define-element) | 
|  | 74 * [Providing a template for the Polymer element](#providing-a-template) | 
|  | 75 * [Providing a script for the Polymer element](#providing-a-script) | 
|  | 76 * [Life-cycle methods](#life-cycle-methods) | 
|  | 77 * [One-way data binding](#one-way-data-binding) | 
|  | 78 * [Setting up event handlers declaratively](#event-handlers) | 
|  | 79 * [Shadow DOM](#in-the-shadows) | 
|  | 80 * [Scoped CSS in a Polymer element](#scoped-css) | 
|  | 81 * [Other resources](#other-resources) | 
|  | 82 | 
|  | 83 ##An example | 
|  | 84 | 
|  | 85 In the example running below, | 
|  | 86 the area within the black rectangle is implemented by a Polymer element, | 
|  | 87 | 
|  | 88 <strong>Try it!</strong> | 
|  | 89 Start and stop the stopwatch. | 
|  | 90 Reset the stopwatch to 00:00 using the **Reset** button. | 
|  | 91 | 
|  | 92 <iframe class="running-app-frame" | 
|  | 93         style="height:175px;width:202px;" | 
|  | 94         src="http://dart-lang.github.com/dart-tutorials-samples/web/target06/sto
     pwatch/web/out/stopwatch.html"> | 
|  | 95 </iframe> | 
|  | 96 | 
|  | 97 To place this Polymer element on an HTML page, you write: | 
|  | 98 | 
|  | 99 {% prettify html %} | 
|  | 100 <tute-stopwatch></tute-stopwatch> | 
|  | 101 {% endprettify %} | 
|  | 102 | 
|  | 103 The counting text, the three buttons along with their actions, | 
|  | 104 and the style are all encapsulated within the Polymer element. | 
|  | 105 The definition of the Polymer element encapsulates and | 
|  | 106 hides the implementation details, | 
|  | 107 which as the user of the element, you care nothing about. | 
|  | 108 | 
|  | 109 When you use tools to inspect the element, | 
|  | 110 you see just the Polymer element's begin and end tag. | 
|  | 111 The contents of the Polymer element are hidden in the *shadow DOM*. | 
|  | 112 | 
|  | 113  | 
|  | 114 | 
|  | 115 With Polymer elements, developers can easily share and use elements | 
|  | 116 with semantically meaningful tags that are easy to share, | 
|  | 117 re-use, and read. | 
|  | 118 | 
|  | 119 ###Overview of the example files | 
|  | 120 | 
|  | 121 Three primary source files implement the stopwatch example: | 
|  | 122 | 
|  | 123 <dl> | 
|  | 124   <dt> | 
|  | 125     <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
     /target06-polymer/stopwatch/web/index.html" target="_blank">index.html</a> | 
|  | 126   </dt> | 
|  | 127   <dd> | 
|  | 128     The primary HTML file for the app. | 
|  | 129     Includes the Polymer bootstrap script and instantiates the Polymer element. | 
|  | 130   </dd> | 
|  | 131   <dt> | 
|  | 132     <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
     /target06-polymer/stopwatch/web/tute_stopwatch.html" target="_blank">tute_stopwa
     tch.html</a> | 
|  | 133   </dt> | 
|  | 134   <dd> | 
|  | 135     The HTML code that defines the Polymer element. | 
|  | 136   </dd> | 
|  | 137   <dt> | 
|  | 138     <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
     /target06-polymer/stopwatch/web/tute_stopwatch.dart" target="_blank">tute_stopwa
     tch.dart</a> | 
|  | 139   </dt> | 
|  | 140   <dd> | 
|  | 141     The Dart class that implements the Polymer element. | 
|  | 142   </dd> | 
|  | 143 </dl> | 
|  | 144 | 
|  | 145 The following diagram shows the structure of the example | 
|  | 146 app and its use of Polymer elements. | 
|  | 147 | 
|  | 148  | 
|  | 149 | 
|  | 150 ##Installing Polymer.dart {#getting-polymer-dart} | 
|  | 151 | 
|  | 152 To use the features provided by Polymer.dart, | 
|  | 153 you need to install the polymer package. | 
|  | 154 If you are unfamiliar with installing packages, | 
|  | 155 refer to | 
|  | 156 <a href="/docs/tutorials/shared-pkgs/">Install Shared Packages</a>, | 
|  | 157 which describes the process in detail. | 
|  | 158 | 
|  | 159 In brief, to install the polymer package: | 
|  | 160 | 
|  | 161 * In the application's `pubspec.yaml` file, | 
|  | 162 add the package to the list of dependencies | 
|  | 163 by adding the package name, `polymer`, to the list. | 
|  | 164 YAML is whitespace-sensitive | 
|  | 165 so take care to indent the package name as shown: | 
|  | 166 | 
|  | 167    | 
|  | 168 | 
|  | 169 * If you are using Dart Editor, | 
|  | 170 when you save pubspec.yaml | 
|  | 171 the editor automatically runs `pub install`. | 
|  | 172 If you are using command line tools, | 
|  | 173 you can run it with the command `pub install`. | 
|  | 174 The installation process | 
|  | 175 recursively installs the polymer.dart package | 
|  | 176 and all the packages that it depends on. | 
|  | 177 | 
|  | 178 ##Including Polymer.dart in your application {#bootstrap} | 
|  | 179 | 
|  | 180 To use Polymer.dart features, such as Polymer elements, | 
|  | 181 you need to include Polymer in both | 
|  | 182 the HTML side and in the Dart side of your app. | 
|  | 183 | 
|  | 184 * In the primary HTML file for your app, | 
|  | 185 you must include `packages/polymer/boot.js` | 
|  | 186 in the <head> section. | 
|  | 187 When using this script, | 
|  | 188 you do not need to include a top-level `main()` function, | 
|  | 189 although you may. | 
|  | 190 **Note:** Use this script in lieu of `packages/browser/dart.js`. | 
|  | 191 | 
|  | 192    | 
|  | 193 | 
|  | 194 * Each Dart file that uses Polymer features | 
|  | 195 needs to import the Polymer library: | 
|  | 196 | 
|  | 197    | 
|  | 198 | 
|  | 199 ##Instantiating a Polymer element {#instantiating} | 
|  | 200 | 
|  | 201 To create an instance of the Polymer element, | 
|  | 202 use the name of the Polymer element just as you would any normal HTML tag. | 
|  | 203 In this example, the tag name is `tute-stopwatch`. | 
|  | 204 | 
|  | 205  | 
|  | 206 | 
|  | 207 Using best practices, | 
|  | 208 the Polymer element definition is in a separate file | 
|  | 209 from where it is instantiated. | 
|  | 210 Use `link` to import the HTML definition file as shown. | 
|  | 211 | 
|  | 212 ##Defining a Polymer element {#define-element} | 
|  | 213 | 
|  | 214 The definition for the tute-stopwatch element is | 
|  | 215 in `tute-stopwatch.html`. | 
|  | 216 A Polymer element definition should be in its own | 
|  | 217 source file so that it can be included by other files. | 
|  | 218 | 
|  | 219 To define a Polymer element, | 
|  | 220 use the <polymer-element> tag and provide a name. | 
|  | 221 | 
|  | 222 {% prettify html %} | 
|  | 223 <polymer-element name="tute-stopwatch"> | 
|  | 224   ... | 
|  | 225 </polymer-element> | 
|  | 226 {% endprettify %} | 
|  | 227 | 
|  | 228 A Polymer element name must have at least one hyphen (`-`). | 
|  | 229 We advise using an identifiable prefix to | 
|  | 230 avoid naming conflicts with elements shared by others | 
|  | 231 and to help identify the project from which the element originates. | 
|  | 232 For example, for all tutorial polymer elements, we use the prefix `tute`. | 
|  | 233 | 
|  | 234 Within the <polymer-element> tag, | 
|  | 235 you can provide a template (appearance) and a script (behavior). | 
|  | 236 UI widgets, like our stopwatch example, | 
|  | 237 typically have both a template and a script. | 
|  | 238 But neither is required. | 
|  | 239 A polymer element with a script and no template is purely functional, | 
|  | 240 for example a [xx]. | 
|  | 241 A polymer element with a template and no script is purely visual, | 
|  | 242 for example a [xx]. | 
|  | 243 | 
|  | 244 {% prettify html %} | 
|  | 245 <polymer-element name="tute-stopwatch"> | 
|  | 246   <template> | 
|  | 247     ... | 
|  | 248   </template> | 
|  | 249   <script type="application/dart" src="tute_stopwatch.dart"> | 
|  | 250   </script> | 
|  | 251 </polymer-element> | 
|  | 252 {% endprettify %} | 
|  | 253 | 
|  | 254 <dl> | 
|  | 255   <dt> <template> </dt> | 
|  | 256   <dd> | 
|  | 257     Describes the element's structure—its user interface. | 
|  | 258     The template comprises any valid HTML code within the <template> tag. | 
|  | 259     The template is rendered when a Polymer element is instantiated. | 
|  | 260     The template can include CSS styles within a <style> tag. | 
|  | 261   </dd> | 
|  | 262 | 
|  | 263   <dt> <script> </dt> | 
|  | 264   <dd markdown="1"> Specifies a Dart script. | 
|  | 265     For Polymer elements, the Dart script is a Dart class | 
|  | 266     that implements the behavior of the element. | 
|  | 267     Life-cycle methods and event handlers join the UI with the Dart code. | 
|  | 268     In this example, the script is in the `tute_stopwatch.dart` file. | 
|  | 269   </dd> | 
|  | 270 </dl> | 
|  | 271 | 
|  | 272 ##Providing a template for the Polymer element {#providing-a-template} | 
|  | 273 | 
|  | 274 Here's the template code for the tute-stopwatch element: | 
|  | 275 | 
|  | 276  | 
|  | 277 | 
|  | 278 The tute-stopwatch template uses a <style> tag, which is optional. | 
|  | 279 These styles are scoped; they affect only | 
|  | 280 the appearance of the Polymer element and the elements it contains. | 
|  | 281 More about this in [Scoped CSS in a Polymer element](#scoped-css). | 
|  | 282 | 
|  | 283 The rest of the code within the template tag | 
|  | 284 is normal HTML with two exceptions: | 
|  | 285 | 
|  | 286 * {% raw %}`{{counter}}`{% endraw %}--a Polymer syntax for | 
|  | 287 [one-way data binding](#one-way-data-binding). | 
|  | 288 | 
|  | 289 * `on-click`--a Polymer element attribute that lets you | 
|  | 290 [declaratively attach a mouse click handler](#event-handlers). | 
|  | 291 to UI elements, such as buttons. | 
|  | 292 Polymer has other attributes for other event types, such as `on-change`. | 
|  | 293 | 
|  | 294 Let's take a look at structure of the Dart code | 
|  | 295 before we get into the details of data binding | 
|  | 296 and event handlers. | 
|  | 297 | 
|  | 298 ##Providing a script for the Polymer element {#providing-a-script} | 
|  | 299 | 
|  | 300 [xx: this is an important section. make it better. slow it down. | 
|  | 301 explain things better. What do you get with PolymerElement? | 
|  | 302 What do you get with ObservableMixin?] | 
|  | 303 | 
|  | 304 The stopwatch example provides the Dart script for the custom | 
|  | 305 element in a separate file called `tute-stopwatch.dart`. | 
|  | 306 The Dart script is a class that provides the implementation | 
|  | 307 for the life-cycle events and event handlers for the Polymer element. | 
|  | 308 This diagram gives an overview of the TuteStopwatch class: | 
|  | 309 | 
|  | 310  | 
|  | 311 | 
|  | 312 When you define a Polymer element you give it a name using the `name` attribute. | 
|  | 313 On the Dart side, a class implements the behavior of the Polymer element. | 
|  | 314 You associate the Dart class with the Polymer element using the `@CustomTag` | 
|  | 315 annotation and the name of the Polymer element. | 
|  | 316 | 
|  | 317  | 
|  | 318 | 
|  | 319 Any Dart class that backs a polymer element | 
|  | 320 must subclass PolymerElement. | 
|  | 321 | 
|  | 322 [xx: more about PolymerElement] | 
|  | 323 | 
|  | 324 [xx: more about ObservableMixin] | 
|  | 325 | 
|  | 326 The class may override one of several [life-cycle methods](#life-cycle-methods) | 
|  | 327 such as the inserted() method you see overridden here. | 
|  | 328 | 
|  | 329 The `start()` method is an event handler for the **Start** button. | 
|  | 330 The event handler is declaratively connected to the button. | 
|  | 331 Refer to [Setting up event handlers declaratively](#event-handlers) to see how. | 
|  | 332 | 
|  | 333 ##Life-cycle methods {#life-cycle-methods} | 
|  | 334 | 
|  | 335 The inserted() method is one of four Polymer element life-cycle methods: | 
|  | 336 | 
|  | 337 * created(): called when an instance of a Polymer element is created. | 
|  | 338 | 
|  | 339 * inserted(): called when an instance of a Polymer element is | 
|  | 340 inserted into the DOM. | 
|  | 341 | 
|  | 342 * removed(): called when an instance of a Polymer element is | 
|  | 343 removed from the DOM. | 
|  | 344 | 
|  | 345 * attributeChanged(): called when an attribute, such as `class`, | 
|  | 346 of an instance of the Polymer element is added, changed, or removed. | 
|  | 347 | 
|  | 348 You can override any of these life-cycle methods. | 
|  | 349 The overriding method | 
|  | 350 *must* call the super class methods first. | 
|  | 351 | 
|  | 352 The stopwatch example overrides the inserted() method | 
|  | 353 to initialize the app. | 
|  | 354 The app needs a reference to each of the three buttons | 
|  | 355 so that it can enable and disable the buttons | 
|  | 356 as appropriate for the state of the app. | 
|  | 357 You'll notice that it gets the buttons by querying | 
|  | 358 its [shadow DOM](#in-the-shadows). | 
|  | 359 | 
|  | 360 ##One-way data binding {#one-way-data-binding} | 
|  | 361 | 
|  | 362 In HTML, use double curly brackets to embed Dart data into your webpage. | 
|  | 363 In Dart use the `@observable` annotation in the Dart code | 
|  | 364 to mark the embedded data. | 
|  | 365 Here, the data is a string called `counter`. | 
|  | 366 | 
|  | 367  | 
|  | 368 | 
|  | 369 This little program uses a periodic Timer to fire an event every second. | 
|  | 370 When the Timer fires, it calls the `updateTImer` callback function, | 
|  | 371 which modifies the `counter` string. | 
|  | 372 Polymer updates the bound area on the HTML page. | 
|  | 373 | 
|  | 374 This type of binding is called _one-way data binding_ | 
|  | 375 because the data can change only on the Dart side. | 
|  | 376 Polymer also supports two-way data binding | 
|  | 377 in which the data can be changed on the HTML side, | 
|  | 378 perhaps with a type of input element, | 
|  | 379 and it changes the value in the Dart code. | 
|  | 380 | 
|  | 381 You can use expressions within the double curly brackets. | 
|  | 382 <a href="http://pub.dartlang.org/packages/polymer_expressions">Polymer expressio
     ns</a> | 
|  | 383 provide the default syntax. | 
|  | 384 | 
|  | 385 Examples include: | 
|  | 386 | 
|  | 387 [xx: include some examples of Polymer expressions] | 
|  | 388 | 
|  | 389 ##Setting up event handlers declaratively {#event-handlers} | 
|  | 390 | 
|  | 391 This example has three buttons, each | 
|  | 392 with an event handler that is written in Dart, | 
|  | 393 but attached to the button declaratively from HTML. | 
|  | 394 | 
|  | 395  | 
|  | 396 | 
|  | 397 In HTML, use the `on-click` attribute | 
|  | 398 to attach a mouse click handler to an HTML element. | 
|  | 399 The value of the attribute is the name of a method | 
|  | 400 in the class that implements the Polymer element. | 
|  | 401 When the user clicks the button the named method is called | 
|  | 402 with three parameters: | 
|  | 403 | 
|  | 404 * the event, which contains information about the event, | 
|  | 405 such as [xx what is of interest here] | 
|  | 406 | 
|  | 407 * detail, which as far as I can tell is never used | 
|  | 408 | 
|  | 409 * and Node, which is the element which fired the event, | 
|  | 410 the **Start** button in this case. | 
|  | 411 | 
|  | 412 You can attach other types of event handlers to other types of input elements. | 
|  | 413 For example, you can use `on-change` to handle events for input text elements | 
|  | 414 when the text changes. | 
|  | 415 | 
|  | 416 ##Shadow DOM {#in-the-shadows} | 
|  | 417 | 
|  | 418 Hey! Remember we mentioned the shadow DOM earlier. | 
|  | 419 Now we get to bring it out of the shadows. | 
|  | 420 | 
|  | 421 The Shadow DOM is key to encapsulation. | 
|  | 422 The DOM tree for a Polymer element is in the shadows, | 
|  | 423 hidden from outside of the Polymer element | 
|  | 424 (unless the Polymer element chooses to reveal them). | 
|  | 425 | 
|  | 426  | 
|  | 427 | 
|  | 428 You can programmatically get items from the shadow DOM | 
|  | 429 by querying a Polymer element's shadow root. | 
|  | 430 | 
|  | 431 {% prettify dart %} | 
|  | 432 startButton = getShadowRoot("tute-stopwatch").query('#startbutton'); | 
|  | 433 stopButton = getShadowRoot("tute-stopwatch").query('#stopbutton'); | 
|  | 434 resetButton = getShadowRoot("tute-stopwatch").query('#resetbutton'); | 
|  | 435 {% endprettify %} | 
|  | 436 | 
|  | 437 Call `getShadowRoot` with the name of the Polymer element. | 
|  | 438 [xx: getShadowRoot returns the shadow root for 'this' instance of | 
|  | 439 the element named] | 
|  | 440 Then use `query` with a CSS selector to get the element(s) of interest. | 
|  | 441 | 
|  | 442 Note that this code queries for each button using the button's id. | 
|  | 443 By querying the shadow root object, | 
|  | 444 you are guaranteed to get the objects from within the Polymer element, | 
|  | 445 not from anywhere else on the page. | 
|  | 446 | 
|  | 447 ##Scoped CSS in a Polymer element {#scoped-css} | 
|  | 448 | 
|  | 449 You can optionally include CSS styles for your Polymer element | 
|  | 450 that applies to the contents of the Polymer element. | 
|  | 451 | 
|  | 452  | 
|  | 453 | 
|  | 454 The primary div element within the template has an id `stopwatch_container`. | 
|  | 455 The styles within the template apply only to the template. | 
|  | 456 So any ID within the template need only be unique within the template. | 
|  | 457 You don't need to worry about naming conflicts on the page. | 
|  | 458 | 
|  | 459 ##Other resources | 
|  | 460 | 
|  | 461 * We converted all tutorial examples that previously used Web UI | 
|  | 462 to use Polymer instead. | 
|  | 463 Checkout the | 
|  | 464 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web">gi
     thub repo</a> | 
|  | 465 to find the source code for all of the Polymer examples. | 
|  | 466 | 
|  | 467 * Check out the | 
|  | 468 <a href="http://www.dartlang.org/polymer-dart/">Polymer.dart</a> | 
|  | 469 home page. | 
|  | 470 | 
|  | 471 * Check out the Polymer project website at | 
|  | 472 <a href="http://www.polymer-project.org/">polymer-project.org</a>. | 
|  | 473 | 
|  | 474 * The next target is going to talk about other nifty polymer.dart features like | 
|  | 475 two-way data binding, xtag, and the <content> tag and shadow DOM. | 
|  | 476 Aren't you excited? | 
|  | 477 | 
|  | 478 Wahoo! | 
|  | 479 | 
|  | 480 Go write some code. | 
|  | 481 | 
|  | 482 {% endcapture %} | 
|  | 483 | 
|  | 484 {% include tutorial.html %} | 
| OLD | NEW | 
|---|