Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/site/docs/tutorials/polymer-intro/index.markdown

Issue 24269013: first draft of polymer element tutorial (Closed) Base URL: https://github.com/dart-lang/dartlang.org.git@master
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 ---
2 layout: default
3 title: "Define a Custom Element"
4 description: "Create a custom HTML element using Polymer."
5 has-permalinks: true
6 tutorial:
7 id: polymer-intro
8 next: fetchdata
9 next-title: "Fetch Data Dynamically"
10 prev: shared-pkgs
11 prev-title: "Install Shared Packages"
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 * Custom elements provide semantically meaningful encapsulation.
19 * Use Polymer.dart to build custom elements.
20 * Bind Dart data to HTML elements.
21 * Declaratively bind event handlers to elements.
22
23 {% endcapture %}
24
25 {% capture sample_links %}
26
27 <p>
28 Get the source code for the samples featured in this target:</p>
29
30 <ul>
31 <li>
32 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web /polymer-intro/stopwatch"
33 target="_blank">stopwatch</a>
34 </li>
35 </ul>
36
37 {% endcapture %}
38
39 {% capture content %}
40
41 <div class="tute-target-title">
42 <h1>{{page.title}}</h1>
43 <h3>Create a custom HTML element using Polymer</h3>
44 </div>
45
46 A custom element is an HTML element you can define yourself,
47 encapsulating appearance and/or behavior
48 within semantically meaningful HTML.
49
50 <aside class="alert">
51 Custom elements are one feature of
52 <a href="http://www.polymer-project.org/"
53 target="_blank">Polymer</a>,
54 a new type of library for the web based on Web Components.
55 <a href="http://www.dartlang.org/polymer-dart/"
56 target="_blank">Polymer.dart</a>
57 is the Dart implementation of Polymer.
58 (Note: Polymer supersedes Web UI.)
59 </aside>
60
61 * [An example](#an-example)
62 * [Installing Polymer.dart](#getting-polymer-dart)
63 * [Including Polymer.dart in your application](#bootstrap)
64 * [Instantiating a custom element](#instantiating)
65 * [Defining a custom element](#define-element)
66 * [Providing a template for the custom element](#providing-a-template)
67 * [Providing a script for the custom element](#providing-a-script)
68 * [Overiding life-cycle methods](#life-cycle-methods)
69 * [Using data binding](#data-binding)
70 * [Setting up event handlers declaratively](#event-handlers)
71 * [Querying the Shadow DOM](#in-the-shadows)
72 * [Styling a custom element](#scoped-css)
73 * [Other resources](#other-resources)
74
75 ##An example
76
77 In the example running below,
78 the LemonChiffon area outlined in black
79 is a custom element implemented using Polymer.
80
81 <strong>Try it!</strong>
82 Start and stop the stopwatch.
83 Reset the stopwatch to 00:00 using the **Reset** button.
84
85 <iframe class="running-app-frame"
86 style="height:220px;width:230px;"
87 src="examples/stopwatch/out/web/index.html">
88 </iframe>
89
90 To place this custom element on an HTML page,
91 import the file with the custom element definition
92 and use the name of the element as an HTML tag:
93
94 {% prettify html %}
95 <link rel="import" href="tute_stopwatch.html">
96 ...
97 <tute-stopwatch></tute-stopwatch>
98 {% endprettify %}
99
100 The counting text, the three buttons along with their actions,
101 and the style are all contained within the custom element.
102 The definition of the custom element encapsulates and
103 hides the implementation details,
104 which as the user of the element, you care nothing about.
105
106 When you use developer tools to inspect the element,
107 you see just the custom element's begin and end tags.
108
109 ![Custom element encapsulates its contents](images/dev-tools-dom.png)
110
111 With custom elements, you can easily create new kinds of elements
112 that have semantically meaningful tags and that are easy to share,
113 reuse, and read.
114
115 ###Overview of the example files
116
117 Three main source files implement the Stopwatch example:
118
119 <dl>
120 <dt>
121 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web /polymer-intro/stopwatch/web/index.html" target="_blank">index.html</a>
122 </dt>
123 <dd>
124 The primary HTML file for the app.
125 Includes the Polymer bootstrap script and instantiates the custom element.
126 </dd>
127 <dt>
128 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web /polymer-intro/stopwatch/web/tute_stopwatch.html" target="_blank">tute_stopwatch .html</a>
129 </dt>
130 <dd>
131 The HTML code that defines the custom element.
132 </dd>
133 <dt>
134 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web /polymer-intro/stopwatch/web/tute_stopwatch.dart" target="_blank">tute_stopwatch .dart</a>
135 </dt>
136 <dd>
137 The Dart class that implements the custom element.
138 </dd>
139 </dl>
140
141 The following diagram shows the structure of the example
142 app and its use of custom elements.
143
144 ![The connections between Dart and HTML](images/connections.png)
145
146 ##Installing Polymer.dart {#getting-polymer-dart}
147
148 To use the features provided by Polymer.dart,
149 you need to install the Polymer package.
150 If you are unfamiliar with installing packages,
151 refer to
152 <a href="/docs/tutorials/shared-pkgs/">Install Shared Packages</a>,
153 which describes the process in detail.
154
155 In brief, to install the Polymer package:
156
157 * In the application's `pubspec.yaml` file,
158 add the package to the list of dependencies
159 by adding the package name, `polymer`, to the list.
160 YAML is whitespace-sensitive,
161 so take care to indent the package name as shown:
162
163 ![Sample pubspec file with polymer dependency](images/sample-pubspec.png)
164
165 * Run `pub install`,
166 which recursively installs the polymer.dart package
167 and all the packages that it depends on.
168 If you are using Dart Editor,
169 when you save pubspec.yaml
170 the editor automatically runs `pub install` for you.
171 If you are using command line tools,
172 you can run it with the command `pub install`.
173
174 ##Including Polymer.dart in your application {#bootstrap}
175
176 To use Polymer.dart features such as custom elements,
177 you need to include Polymer in both
178 the HTML side and the Dart side of your app.
179
180 * In the primary HTML file for your app,
181 include `packages/polymer/boot.js`
182 in the &lt;head&gt; section.
183 When using this script,
184 you do not need to define a top-level `main()` function,
185 although you can.
186 **Note:** Use this script instead of `packages/browser/dart.js`.
187
188 ![Include the Polymer bootstrap script](images/bootstrap-script.png)
189
190 * In your Dart code, import the Polymer library:
191
192 ![Import the Polymer library](images/polymer-library.png)
193
194 ##Instantiating a custom element {#instantiating}
195
196 To create an instance of a custom element,
197 use the name of the custom element just as you would any normal HTML tag.
198 In this example, the tag name is `tute-stopwatch`.
199
200 ![Instantiate a custom element with a custom tag](images/polymer-element-instant iation.png)
201
202 Using best practices,
203 the custom element definition is in a separate file.
204 Use `link [rel="import"]` to import the HTML definition file as shown.
205
206 ##Defining a custom element {#define-element}
207
208 The definition for the &lt;tute-stopwatch&gt; element is
209 in
210 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/pol ymer-intro/stopwatch/web/tute_stopwatch.html" target="_blank">tute_stopwatch.htm l</a>.
211 A custom element definition should be in its own
212 source file so that it can be included by other files.
213 An HTML file that contains the definition for a custom element
214 does not need &lt;html&gt;, &lt;head&gt;, or &lt;body&gt; tags.
215
216 To define a custom element,
217 use the &lt;polymer-element&gt; tag and provide a name.
218
219 {% prettify html %}
220 <polymer-element name="tute-stopwatch">
221 ...
222 </polymer-element>
223 {% endprettify %}
224
225 A custom element name must have at least one hyphen (`-`).
226 We advise using an identifiable prefix to
227 avoid naming conflicts with elements shared by others
228 and to help identify the project from which the element originates.
229 For example, for tutorial custom elements, we use the prefix `tute`.
230
231 Within the &lt;polymer-element&gt; tag,
232 you can provide a template (appearance) and a script (behavior).
233 UI widgets, like our Stopwatch example,
234 typically have both a template and a script,
235 but neither is required.
236 A custom element with a script and no template is purely functional.
237 A custom element with a template and no script is purely visual.
238
239 {% prettify html %}
240 <polymer-element name="tute-stopwatch">
241 <template>
242 ...
243 </template>
244 <script type="application/dart" src="tute_stopwatch.dart">
245 </script>
246 </polymer-element>
247 {% endprettify %}
248
249 <dl>
250 <dt> &lt;template&gt; </dt>
251 <dd>
252 Describes the custom element's structure&mdash;its user interface.
253 The template comprises any valid HTML code within the &lt;template&gt; tag.
254 When the custom element is instantiated,
255 the instance is created from the template.
256 The template can include CSS styles within a &lt;style&gt; tag.
257 </dd>
258
259 <dt> &lt;script&gt; </dt>
260 <dd markdown="1"> Specifies a Dart script.
261 For custom elements, the Dart script is a Dart class
262 that implements the behavior of the element.
263 The class typically overrides some
264 life-cycle methods and provides event handlers
265 that join the UI with its programmatic behavior.
266 In this example, the script is in
267 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web /polymer-intro/stopwatch/web/tute_stopwatch.dart" target="_blank">tute_stopwatch .dart</a>.
268 </dd>
269 </dl>
270
271 ##Providing a template for the custom element {#providing-a-template}
272
273 Here's the template code for the tute-stopwatch element:
274
275 ![The template code for the tute-stopwatch element](images/template-code.png)
276
277 The tute-stopwatch template uses a &lt;style&gt; tag, which is optional.
278 These styles are scoped; they affect only
279 the appearance of the custom element and the elements it contains.
280 More about scoped CSS in [Styling a custom element](#scoped-css).
281
282 The rest of the code within the &lt;template&gt; tag
283 is normal HTML, with two exceptions:
284
285 |---|---|
286 | `{``{``counter}}` | Uses a Polymer syntax to [bind Dart data](#data-binding) t o the HTML page. The double curly braces are commonly known as a "double mustach e". |
287 | `on-click` | Uses Polymer [declarative event mapping](#event-handlers), which allows you to set up event handlers for a UI element. `on-click` sets up an even t handler for mouse clicks. Polymer has mappings for other event types, such as `on-change` for input change events. |
288 {: .table}
289
290 Let's take a look at the structure of the Dart code
291 before we get into the details of data binding, event handlers,
292 and scoped CSS.
293
294 ##Providing a script for the custom element {#providing-a-script}
295
296 On the Dart side, a class implements the behavior of the custom element.
297 You associate the Dart class with the custom element using the `@CustomTag`
298 annotation and the name of the custom element.
299
300 ![Two parts to a custom element definition](images/polymer-element-definition.pn g)
301
302 This diagram gives an overview of the TuteStopwatch class:
303
304 ![The script code for the tute-stopwatch element](images/dart-script-code.png)
305
306 Any Dart class that backs a Polymer element must subclass PolymerElement.
307 If you want to use data binding, the class must also use ObservableMixin.
308
309 {% comment %}
310 [xx: more about PolymerElement]
311 [xx: more about ObservableMixin]
312 {% endcomment %}
313
314 The class can respond to life-cycle milestones
315 by overriding [life-cycle methods](#life-cycle-methods).
316 For example, the TuteStopwatch class overrides the `inserted()`
317 method&mdash;which is called when the element is inserted
318 into the DOM&mdash;to initialize the app.
319
320 The `start()` method is an event handler for the **Start** button.
321 The event handler is declaratively connected to the button.
322 Refer to [Setting up event handlers declaratively](#event-handlers) to see how.
323
324 ##Overriding life-cycle methods {#life-cycle-methods}
325
326 A custom element has four life-cycle methods
327 that it can override:
328
329 |---|---|
330 | `created()` | Called when an instance of a custom element is created. |
331 | `inserted()` | Called when an instance of a custom element is inserted into th e DOM. |
332 | `removed()` | Called when an instance of a custom element is removed from the DOM. |
333 | `attributeChanged()` | Called when an attribute, such as `class`, of an instan ce of the custom element is added, changed, or removed. |
334 {: .table}
335
336 You can override any of these life-cycle methods.
337 The overriding method
338 *must* call the super class method first.
339
340 The Stopwatch app overrides the `inserted()` method because it
341 needs a reference to each of the three buttons
342 so that it can enable and disable them.
343 When a tute-stopwatch custom element is inserted into the DOM
344 the buttons have been created, so the references to them
345 will be available when the inserted() method is called.
346 You'll notice that it gets the buttons by
347 [querying the custom element's shadow root](#in-the-shadows).
348
349 {% prettify dart %}
350 void inserted() {
351 super.inserted();
352 startButton = getShadowRoot('tute-stopwatch').query('#startButton');
353 stopButton = getShadowRoot('tute-stopwatch').query('#stopButton');
354 resetButton = getShadowRoot('tute-stopwatch').query('#resetButton');
355
356 stopButton.disabled = true;
357 resetButton.disabled = true;
358 }
359 {% endprettify %}
360
361 ##Using data binding {#data-binding}
362
363 In the HTML definition of a custom element,
364 use double curly brackets to embed Dart data into the webpage.
365 In your Dart code, use the `@observable` annotation
366 to mark the embedded data.
367 Here, the data is a string called `counter`.
368
369 ![One-way data binding](images/one-way-data-binding.png)
370
371 The tute-stopwatch element uses a periodic
372 <a href="https://api.dartlang.org/dart_async/Timer.html" target="_blank">Timer</ a>
373 to fire an event every second.
374 When the Timer fires, it calls the `updateTimer()` method,
375 which modifies the `counter` string.
376 Polymer takes care of updating the HTML page with the new string.
377
378 This type of binding is called _one-way data binding_
379 because the data can change only on the Dart side.
380 Polymer also supports two-way data binding.
381 In two-way data binding, when data changes on the HTML side&mdash;for example
382 with an input element&mdash;the value in the Dart code changes to match.
383
384 You can use expressions within the double curly brackets.
385 <a href="http://pub.dartlang.org/packages/polymer_expressions"
386 target="_blank">Polymer expressions</a>
387 provide the default syntax. Examples of allowable expressions include:
388
389 |---|---|
390 | `{``{``myObject.aProperty}}` | Property access. |
391 | `{``{``!empty}}` | Operators, like the logical not operator. |
392 | `{``{``myList[3]}}` | List indexing. |
393 | `{``{``myFilter()}}` | Data filtering. |
394 {: .table}
395
396 ##Setting up event handlers declaratively {#event-handlers}
397
398 This example has three buttons, each
399 with an event handler that is written in Dart,
400 but attached to the button declaratively from HTML.
401
402 ![Declaratively attach a click handler](images/click-handler.png)
403
404 In HTML, use the `on-click` attribute
405 to attach a mouse click handler to an HTML element.
406 The value of the attribute must be the name of a method
407 in the class that implements the custom element.
408 When the user clicks the button, the specified method is called
409 with three parameters:
410
411 * An
412 <a href="https://api.dartlang.org/dart_html/Event.html" target="_blank">Event</a >
413 that contains information about the event,
414 such as its type and when it occurred.
415
416 * The _detail_ object can provide additional, event-specific information.
417
418 * The <a href="https://api.dartlang.org/dart_html/Node.html" target="_blank">Nod e</a>
419 that fired the event&mdash;the **Start** button in this case.
420
421 You can attach event handlers for other kinds of events.
422 For example, you can use `on-change` to handle events for input text elements
423 when the text changes.
424
425 Refer to
426 [Declarative event mapping](http://www.polymer-project.org/polymer.html#declarat ive-event-mapping)
427 for further details.
428
429 ##Querying the shadow root {#in-the-shadows}
430
431 The Shadow DOM is key to encapsulation.
432 The DOM subtree for a custom element is
433 hidden from outside of the custom element.
434
435 ![Shadow DOM for tute-stopwatch custom element](images/shadow-dom.png)
436
437 You can programmatically get items from the Shadow DOM
438 by querying a custom element's _shadow root_&mdash;a
439 special node from which an instance of a custom element is rendered.
440
441 {% prettify dart %}
442 startButton = getShadowRoot('tute-stopwatch').query('#startbutton');
443 stopButton = getShadowRoot('tute-stopwatch').query('#stopbutton');
444 resetButton = getShadowRoot('tute-stopwatch').query('#resetbutton');
445 {% endprettify %}
446
447 Call `getShadowRoot()` with the name of the custom element.
448 The `getShadowRoot()` method returns the shadow root element
449 for this instance of the specified element.
450 Use `query()` with a CSS selector to get the element(s) of interest.
451
452 Note that this code uses `query()` to get each button by ID.
453 By querying the shadow root object rather than the DOM,
454 you are guaranteed to get the objects from within the custom element,
455 not from anywhere else on the page.
456
457 ##Styling a custom element {#scoped-css}
458
459 You can optionally include CSS styles for your custom element
460 that apply only to the contents of the custom element.
461
462 ![Scoped CSS styling](images/css-styling.png)
463
464 The `@host` rule allows you to target and style an element internally,
465 from within its definition.
466 The `:scope` pseudo-class refers to the custom element itself.
467 The only selectors that work in `@host` are those targeting the host element its elf.
468 So you don't need to worry about naming conflicts on the page.
469 Any CSS selectors within the template need to be unique only within the template .
470
471 For further details about styling custom elements,
472 refer to
473 [A Guide to Styling Elements](http://www.polymer-project.org/articles/styling-el ements.html)
474
475 ##Other resources
476
477 Use these other resources to learn more about Polymer:
478
479 * The tutorial
480 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web"
481 target="_blank">github repo</a>
482 contains many examples that use Polymer,
483 including samples that have been converted from Web UI.
484
485 * The
486 <a href="http://www.dartlang.org/polymer-dart/"
487 target="_blank">Polymer.dart</a> homepage provides information
488 specific to the Dart port of the Polymer project.
489
490 * The Polymer project website
491 <a href="http://www.polymer-project.org/"
492 target="_blank">polymer-project.org</a>
493 contains information about the Polymer project as a whole.
494
495 {% endcapture %}
496
497 {% include tutorial.html %}
OLDNEW
« no previous file with comments | « src/site/docs/tutorials/polymer-intro/images/template-code.png ('k') | src/site/docs/tutorials/shared-pkgs/index.markdown » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698