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

Side by Side Diff: src/site/articles/dart-web-components/index.markdown

Issue 11066080: Initial version of Dart web components article (Closed) Base URL: git@github.com:sigmundch/dartlang.org.git@master
Patch Set: moved generated code elsewhere Created 8 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
« no previous file with comments | « src/site/_plugins/code_sample.rb ('k') | src/site/css/style.css » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 ---
2 layout: default
3 title: "Dart Web Components"
4 rel:
5 author: siggi-cherem
6 description: "A brief introduction to Dart web components."
7 has-permalinks: true
8 ---
9
10 # {{ page.title }}
11 _Written by ...<br />
Kathy Walrath 2012/10/09 23:16:57 update the next 3 lines (of course)
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done. thanks :) - I looked at the other articles,
12 July 2012 <br />
13 Updated: September 2012_
14
15 ## Dart web components
Kathy Walrath 2012/10/09 23:16:57 Delete this line (already covered by page.title,
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
16
17 {% comment %}
18
19 README --- General notes about editing this file:
20
21 * This file is processed by liquid, which evaluates {{ var }} and removes the
22 \{\{ and \}\} symbols from the code. Because we use \{\{\}\} in our template
23 expressions, we need to escape them in a special way. Unfortunately using
24 \{\{\}\} within code makes the backslash show up. There are 2 ways to work
25 around this:
26 * Doing {{'{{'}}: lyquid evaluates it as a string expression returning \{\{.
27 * Using \{\% raw \%\} blocks.
28
29 * the codesample blocks are an extension added to jekyll written as 'liquid'
30 blocks. The meaning of a block like this:
31 \{\% codesample 80 \%\}
32
33 text
34 \{\% sample 10 20 url \%\}
35 \{\% endcodesample \%\}
36 is that we'll create a table, the first colum will have sample source code (in
37 this case "text"). This code can have a \{\% highlight \%\} section, but other
38 than that, no markdown is supported here :(. The column width is specified as
39 the first argument of the codesample tag above it (in this example 80 means
40 80%). The \{\% sample \%\} tag defines the width, height, and url for an iframe
41 that will contain the runnining version of the code sample.
42
43 {% endcomment %}
44
45 [Dart web components][dwc] are a combination of templating, data-binding, and
Kathy Walrath 2012/10/09 23:16:57 GLOBAL: data-binding -> data binding (If you were
Kathy Walrath 2012/10/09 23:16:57 Are web components really techniques? I think of t
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 nice, thanks. Done.
46 encapsulation techniques for writing web applications at scale.
47
48 There are many UI frameworks in the web intended for writing web applications in
Kathy Walrath 2012/10/09 23:16:57 "There are..." is a vague way to start (those 2 wo
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
49 JS, for example [backbone], [ember.js][ember], and [angularjs][angular].
50 Recently, the web community has been pushing to include some of the common ideas
51 of these frameworks directly into browser platform. A result of that has been
Kathy Walrath 2012/10/09 23:16:57 into -> into the A result of that -> A result
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
52 added features like Shadow Dom and [Web Components][wc], and other experimental
Kathy Walrath 2012/10/09 23:16:57 No link to Shadow DOM? We should standardize on t
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
Jennifer Messerly 2012/10/10 01:18:29 Could you add a link to Shadow DOM? http://dvcs.w3
53 and cool ideas like [Model Driven Views][mdv].
54
55 Dart web components have a similar role in Dart. They are the result of
Kathy Walrath 2012/10/09 23:16:57 Could be shorter/clearer. How about. Dart web com
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
56 combining together design ideas of web components and model-driven views, and
57 adapting them to include Dart in the picture. The dart web component tools will
Kathy Walrath 2012/10/09 23:16:57 I was confused by "dart web component tools". We u
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 good points... fixed.
58 take advantage of advanced browser features if they exist in your browser, but
59 otherwise they will emulate any missing feature.
60
61 In this article, we'll walk through some examples that illustrate how to write
62 and use Dart Web Components. Soon we'll be creating a document with a detailed
63 specification (link TBR), and another document with instructions on how to use
64 the Dart Web Component tools (link TBR).
65
66 ## MDV Templates in Dart
Kathy Walrath 2012/10/09 23:16:57 Templates -> templates (we use Title Caps for pag
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
67
68 Most UI frameworks provide some form of templating to declare views with a
69 succint declarative syntax. Dart web components follow closely
Kathy Walrath 2012/10/09 23:16:57 follow closely -> closely follow
Kathy Walrath 2012/10/09 23:16:57 succint -> succinct follow closely -> closely foll
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
70 the syntax of [Model Driven Views][mdv] (MDV), which is basically
Kathy Walrath 2012/10/09 23:16:57 the syntax of ... MDV -> the MDV syntax
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
71 HTML with small extensions to enable the following features:
72
73 * **one-way data-binding**: how to embed data into your UI;
Kathy Walrath 2012/10/09 23:16:57 We usually capitalize the first words in a list. A
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 Done.
74 * **two-way data-binding**: how to keep data in sync with UI changes;
75 * **events listeners**: how to easily attach code that reacts to UI events;
76 * **conditionals**: how to selectively show parts of the UI; and
77 * **loops**: how to construct lists and tables by iterating over collections.
78
79 We made some changes to make sure that using Dart with MDV feels natural, but
80 otherwise all the concepts from MDV are available here. Let's take a look at
81 examples for each of these features.
82
83 ### Data-bindings
Kathy Walrath 2012/10/09 23:16:57 Should this be "One-way data binding"?
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 yes :) thanks
84
85 You can inject data in your template by simply using `{{'{{'}} expresions }}`.
Kathy Walrath 2012/10/09 23:16:57 "by simply using" -> "using" expresions -> expres
Siggi Cherem (dart-lang) 2012/10/09 23:51:08 good point, no it should be singular
86 The example below shows a simple hello world program where the value of the dart
87 top-level variable `dataValue` is injected in the page automatically. The
88 right column shows the app generated from this code running in an iframe.
89
90 {% codesample 90 %}
91 {% highlight html %}
92 {% raw %}
93 <html><body>
94 <div>Hello {{dataValue}}!</div>
95 <script type="application/dart">
96 String dataValue;
97 main() {
98 var today = new Date.now();
99 dataValue = 'world ${today.year}-${today.month}-${today.day}';
100 }
101 </script>
102 </body></html>
103 {% endraw %}
104 {% endhighlight %}
105 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/helloworld.html.html %}
106 {% endcodesample %}
107
108 The template expression we just saw above is what we call a **one-way data
109 binding**. Like in many other UI libraries and frameworks, we automatically
110 watch for changes in your data and ensure the UI is up-to-date whenever the data
111 changes.
112
113 Dart web components do this by using the `watchers.dart` library (included with
114 the dart web components package). You can listen for changes and notify everyone
115 when changes might occur. The following example illustrates how you would
116 manually use this library:
117
118 {% codesample 90 %}
119 {% highlight html %}
120 {% raw %}
121 <html><body>
122 <div>Hello counter: {{count}}</div>
123 <script type="application/dart">
124 import 'dart:html';
125 import 'package:web_components/watcher.dart' as watchers;
126 int count;
127 main() {
128 count = 0;
129 window.setInterval(() {
130 count++;
131 watchers.dispatch();
132 }, 1000);
133 }
134 </script>
135 </body></html>
136 {% endraw %}
137 {% endhighlight %}
138 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/counter.html.html %}
139 {% endcodesample %}
140
141 The code manually invokes `watchers.dispatch()` to make a change visible to the
142 UI. Every now and then it is useful to access watchers directly, but we have
143 found that we often don't have to manually write these calls. In particular,
144 Dart web components will automatically make the dispatch call when using
145 common features like two-way binding and attaching event listeners.
146
147 ### Two-way data bindings
148
149 Two-way data bindings lets us define that we want a DOM element's value
150 (typically an input box or a check box) to be kept in sync with the value of a
151 Dart variable. The following example creates a two way binding between `str` and
152 `input.value`. We declare this binding by writing the attribute
153 `data-bind="value:str"`.
154
155 {% codesample 90 %}
156 {% highlight html %}
157 {% raw %}
158 <html><body>
159 <div>
160 Input:
161 <input type="text" data-bind="value:str" placeholder="type something here">
162 <div> Value: {{str}}</div>
163 <div> Length: {{str.length}}</div>
164 </div>
165 <script type="application/dart">
166 String str = '';
167 main() {}
168 </script>
169 </body></html>
170 {% endraw %}
171 {% endhighlight %}
172 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/twoway.html.html %}
173 {% endcodesample %}
174
175 This is a simple example where Dart web components automatically dispatch
176 events for data-model changes. In particular, whenever you update the value of
177 the text box, the string and it's length will be updated in other parts of the
178 UI.
179
180 ### Data-binding expressions
181
182 We want to make Dart web components have, to a great extend, feature and design
183 parity with MDV. For this reason, we try to match the same syntax of their
184 template language where it is appropriate. MDV restricts data-binding
185 expressions to an expression language containing variables, field dereferences,
186 and array accesses. This means that expressions in MDV templates would likely be
187 valid Dart and valid JS as well. That also means that advanced Dart expressions
188 are not valid between `{{'{{'}}expressions}}`, however you can always hide
189 complex expressions under a getter in Dart and use the getter property within
190 the template.
191
192 A full specification of the expression syntax will be available soon in our
193 [specification document (link TBR)][].
194
195 ### Conditionals
196
197 Template conditionals allow you to selectively activate parts of the UI. We
198 write a conditional by wrapping a portion of the UI in a `<template>` tag and
199 writing the condition in an attribute of the form `instantiate="if expr"`. For
200 instance, the following example only shows `They match!` when both input boxes
201 have the same text:
202
203 {% codesample 90 %}
204 {% highlight html %}
205 {% raw %}
206 <html><body>
207 <div>
208 <div> Input1: <input type="text" data-bind="value:str1"></div>
209 <div> Input2: <input type="text" data-bind="value:str2"></div>
210 <template instantiate="if str1 == str2">
211 <div>They match!</div>
212 </template>
213 </div>
214 <script type="application/dart">
215 String str1 = '';
216 String str2 = '';
217 main() {}
218 </script>
219 </body></html>
220 {% endraw %}
221 {% endhighlight %}
222 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/matchstrings.html.html %}
223 {% endcodesample %}
224
225 ### Loops
226
227 Template loops allow us to iterate over iterable Dart collections. The following
228 example shows a fun little app that has search as you type. We use the two-way
229 data-binding to store the `query` string, then we compute a filtered set of
230 results and display it using a looping construct.
231
232 {% codesample 90 %}
233 {% highlight html %}
234 {% raw %}
235 <html><body>
236 <div>
237 <span>Search for something:</span>
238 <input type="text" data-bind="value:query">
239 <div>
240 <template instantiate='if noMatches'><span>No matches</span></template>
241 <template instantiate='if !noMatches'><span>Top results:</span></template>
242 </div>
243 <div><ul>
244 <template iterate='fruit in results'>
245 <li>{{fruit}}</li>
246 </template>
247 </ul></div>
248 </div>
249 <script type="application/dart">
250 String query = '';
251 List<String> values = const [ 'Apple', 'Apricot', 'Avocado', 'Banana',
252 'Blackberry', 'Blackcurrant', 'Blueberry', 'Currant', 'Cherry',
253 'Clementine', 'Date', 'Durian', 'Fig', 'Gooseberry', 'Grape',
254 'Grapefruit', 'Guava', 'Huckleberry', 'Kiwi', 'Lemon', 'Lime',
255 'Lychee', 'Mandarine', 'Mango', 'Cantaloupe', 'Honeydew melon',
256 'Nectarine', 'Orange', 'Peach', 'Pear', 'Plum', 'Pineapple',
257 'Pomegranate', 'Raspberry', 'Redcurrant', 'Star fruit', 'Strawberry',
258 'Tangerine', 'Tomato', 'Watermelon'];
259
260 List<String> get results {
261 var res = values.filter(
262 (v) => v.toLowerCase().contains(query.toLowerCase()));
263 if (res.length > 20) {
264 res.length = 20;
265 res.add('... and many more');
266 }
267 return res;
268 }
269
270 bool get noMatches => results.isEmpty();
271
272 main() {}
273 </script>
274 </body></html>
275 {% endraw %}
276 {% endhighlight %}
277 {% sample 300px 600px http://dart-lang.github.com/dart-web-components/example/ex plainer/fruitsearch.html.html %}
278 {% endcodesample %}
279
280
281 ### Listen to UI events
282
283 Templates also gives us a succint way to listen for arbitrary UI events and
284 associate those events with Dart code. We do this by using `data-action`
285 attributes. Here is an example that listens for click events:
286
287 {% codesample 90 %}
288 {% highlight html %}
289 {% raw %}
290 <html><body>
291 <div>
292 <button data-action="click:increment">Click me</button>
293 <span>(click count: {{count}})</span>
294 </div>
295 <script type="application/dart">
296 int count = 0;
297 void increment(e) { count++; }
298 main() {}
299 </script>
300 </body></html>
301 {% endraw %}
302 {% endhighlight %}
303 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/clickcount.html.html %}
304 {% endcodesample %}
305
306
307 ### Templating summary
308
309 Templates solve one part of the problem in building web applications: reducing
310 the amount of boilerplate code that is used to set up a typical
311 model-view-viewmodel architecture. One-way databindings, two-way databindings,
312 and data-action listeners, help reduce the need for manually creating controller
313 objects that do these bindings by hand. If we combine bindings, conditionals,
314 and loops, we have a formula to create simple and sophisticated views in a
315 declarative fashion.
316
317 However, templating alone is not enough. We need mechanisms to encapsulate and
318 abstract views so we can scale to build larger web apps. This is were we need
319 web components.
320
321 ## Web Components in Dart
322
323 Web components provide a way to create encapsulated reusable views, which will
324 be useful to build medium and large applications. A web component basically
325 includes a view, some data, and behavior. In our case, views are described in
326 terms of templates, while data and behavior are written directly in Dart.
327
328 ### Declaring a component
329
330 Web components are declared using a special `<element>` tag. For example, we can
331 take the click-count example above and make it a component as follows:
332
333 {% highlight html %}
334 {% raw %}
335 <html><body>
336 <element name="x-counter" constructor="CounterComponent" extends="div">
337 <template>
338 <div>
339 <button data-action="click:increment">Click me</button>
340 <span>(click count: {{count}})</span>
341 </div>
342 </template>
343 <script type="application/dart">
344 import 'package:web_components/web_component.dart';
345
346 class CounterComponent extends WebComponent {
347 int count = 0;
348 void increment(e) { count++; }
349 }
350 </script>
351 </element>
352 <!-- more below... -->
353 </body></html>
354 {% endraw %}
355 {% endhighlight %}
356
357 The `<element>` tag basically declares a component whose view is defined
358 under the child `<template>` tag, and whose behavior code is embedded or sourced
359 by the child `<script>` tag.
360
361 Components can be thought as if they are extending DOM nodes, their declaration
362 indicates which DOM node they extend from using the `extends` attribute. The
363 attribute `constructor="CounterComponent"` indicates that this component's
364 behavior is defined in the `CounterComponent` class. Today, this class must
365 extend from `WebComponent`, but in the future it will be possible to extend
366 directly from the DOM Node that we declared in the `extends` attribute. For
367 instance, `class CounterComponent extends DivElement ...`.
368
369 The `<element>` tag also declares the component's name with the `name`
370 attribute. This name will be used to instantiate this component later on.
371
372 ### Instantiating a component
373
374 Instantiating a component can be done in two ways: using its name as a tag, e.g.
375 `<x-counter></x-counter>` or using setting the `is` attribute on the
376 tag that the component extends from. For example,
377
378 {% codesample 90 %}
379 {% highlight html %}
380 {% raw %}
381 <html><body>
382 <!-- ... element declared as above -->
383 <div is="x-counter"></div>
384 <script type="application/dart">
385 main(){}
386 </script>
387 </body></html>
388 {% endraw %}
389 {% endhighlight %}
390 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/countcomponent.html.html %}
391 {% endcodesample %}
392
393
394 ### Passing data to a component
395
396 All of the public fields in a component declaration can be initialized directly
397 when we instantiate a component. We can do this by writing a special
398 `data-value` attribute in the HTML. For instance, the following example
399 instantiates two click-counter components (declared just like above), but
400 initializes the `count` field of the component to a different value each time.
401
402 {% codesample 90 %}
403 {% highlight html %}
404 {% raw %}
405 <html><body>
406 <!-- ... element declared as above -->
407 <div is="x-counter" data-value="count: myNumber"></div>
408 <div is="x-counter" data-value="count: 5"></div>
409 <script type="application/dart">
410 int myNumber = 12;
411 main(){}
412 </script>
413 </body></html>
414 {% endraw %}
415 {% endhighlight %}
416 {% sample 300px 200px http://dart-lang.github.com/dart-web-components/example/ex plainer/countcomponent5.html.html %}
417 {% endcodesample %}
418
419 ### Working at scale
420
421 When developing larger web applications, it is really useful to be able to split
422 the work and divide pieces of your application in multiple files. It is also
423 useful to create reusable components that you embed in several places of your
424 application or even across several applications.
425
426 Web components allows us to do import other components using `<link
427 rel="components">` tags. For example, suppose we created a file
428 `clickcounter.html` that contains the declaration of the click-counter component
429 as we had above. Then, our last example could be rewritten as follows:
430
431 {% highlight html %}
432 {% raw %}
433 <html>
434 <head>
435 <link rel="components" href="clickcounter.html">
436 </head>
437 <body>
438 <div is="x-counter" data-value="count: myNumber"></div>
439 <div is="x-counter" data-value="count: 5"></div>
440 <script type="application/dart">
441 int myNumber = 12;
442 main(){}
443 </script>
444 </body>
445 </html>
446 {% endraw %}
447 {% endhighlight %}
448
449 ### Upcoming features
450
451 We are still adding features and making changes to Dart web components. Here are
452 some of the features we are working on:
453
454 * Support for sub-components. Using a special `<content>` tag, a component
455 can embed nodes that will be provided when instantiating it. For instance,
456 you could write a component that puts a frame around an image as follows:
457
458 {% highlight html %}
459 {% raw %}
460 <html>
461 <body>
462 <element name="x-myframe">
463 <template>
464 <!-- some complex wrapping happens here ... -->
465 <div class="framestyle">...<content></content>...</div>
466 </template>
467 </element>
468
469 <div is="x-myframe">
470 <!-- img will be included where we wrote <content> above -->
471 <img src="...">
472 </div>
473 </body>
474 </html>
475 {% endraw %}
476 {% endhighlight %}
477
478 * Alternative MDV conditional and listing constructs. Instead of using a
479 `<template>` tags, you will be able to use `instantiate` and
480 `iterate` attributes directly on any element. This is important because in
481 some parts of the HTML is not valid to write `<template>` tags. For example,
482 this feature will make it possible to iterate on table rows and cells.
483
484 ## Developing and using Dart web components
485
486 We are making several tools available to make it easy to create and deploy
487 projects that use dart web components. We have a compiler tool that can be run
488 offline to generate efficient code for your components. The generated code will
489 try to use the native features available in browsers, but otherwise it will
490 resort to other techniques to ensure that the semantics of dart web components
491 are the same everywhere.
492
493 We have added integration with the Dart editor, so that changes to source files
494 can be compiled automatically in the background. We are also developing an
495 extension for dartium that will be able to compile components on the fly as
496 you load them. Both the editor and dartium integration will provide you with a
497 smooth edit/refresh cycle.
498
499 More details about our tools will be available soon [(link TBR)][].
500
501 ## Exploring More
502
503 There are many resources to explore and learn more about Dart web components.
504 Check out our Dartisans episode on this topic:
505
506 <iframe width="560" height="315" src="http://www.youtube.com/embed/zUdQkSwslzc" frameborder="0" allowfullscreen></iframe>
507
508 You can also follow the project in [github][dwc], track and file bugs in our
509 [issue tracker][bugs], and play with other examples in our repo, like our port
510 of [todomvc][todomvcindwc].
511
512 If you have any questions, feel free to send us email directly at
513 [misc@dartlang.org](mailto:misc@dartlang.org).
514
515
516 [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
517 [mdv]: http://code.google.com/p/mdv/
518 [dwc]: https://github.com/dart-lang/dart-web-components/
519 [bugs]: https://github.com/dart-lang/dart-web-components/issues
520 [backbone]: http://backbonejs.org/
521 [angular]: http://angularjs.org/
522 [ember]: http://emberjs.com/
523 [todomvcindwc]: https://github.com/dart-lang/dart-web-components/tree/master/exa mple/todomvc
OLDNEW
« no previous file with comments | « src/site/_plugins/code_sample.rb ('k') | src/site/css/style.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698