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

Side by Side Diff: src/site/articles/trydart/index.markdown

Issue 35913002: Try Dart 1 hour experience first draft (Closed) Base URL: https://github.com/dart-lang/dartlang.org.git@master
Patch Set: rough draft ready for review (2nd try after errors) 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
« no previous file with comments | « src/site/articles/trydart/images/run.png ('k') | src/site/articles/trydart/trydart.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: "Try Dart"
4 description: "Write some Dart code. Learn some stuff."
5 has-permalinks: true
6 tutorial:
7 id: trydart
8 js:
9 - url: /js/os-switcher.js
10 defer: true
11 - url: /js/editor-downloads-analytics.js
12 defer: true
13 - url: /js/editor-version.js
14 defer: true
15 header:
16 css: ["/articles/trydart/trydart.css"]
17 ---
18
19 # {{ page.title }}
20
21 ## Got an hour? Write a Dart app.
22
23 In this code lab,
24 you build a pirate badge generator from a skeleton app.
25
26 <strong>Build this app!</strong>
27
28 <iframe class="running-app-frame"
29 style="height:220px;width:530px;"
30 src="examples/6-piratebadge_json/piratebadge.html">
31 </iframe>
32
33 <hr>
34
35 ## The Map
36
37 * [Step 0: Set up](#set-up)
38 * [Step 1: Run the skeleton app](#step-one)
39 * [Step 2: Add an input field](#step-two)
40 * [Step 3: Add a button](#step-three)
41 * [Step 4: Create a class](#step-four)
42 * [Step 5: Save to local storage](#step-five)
43 * [Step 6: Read names from JSON file using HttpRequest](#step-six)
44 * [Step 7: What next?](#step-seven)
45
46
47 <hr>
48
49 ## Step 0: Set up {#set-up}
50
51 In this step, you download Dart and get the sample code.
52
53 #### <i class="icon-anchor"> </i> Get Dart.
54
55 <div class="trydart-step-details" markdown="1">
56 If you haven't already done so,
57 get the Dart download.
58
59 {% include downloads/_dart-editor.html %}
60
61 <p markdown="1">
62 The Dart tools
63 work in recent versions of
64 {% include os-choices.html %}
65 Having trouble? Go to the
66 [Troubleshooting Dart Editor](/tools/editor/troubleshoot.html) page.
67 </p>
68 </div>
69
70 #### <i class="icon-anchor"> </i> Start the Editor.
71
72 <div class="trydart-step-details">
73 Start Dart Editor by double clicking its icon
74 <img src="/imgs/Dart_Logo_21.png"
75 width="21" height="21" alt="Dart Editor icon">.
76 </div>
77
78 #### <i class="icon-anchor"> </i> Get the sample code.
79
80 <div class="trydart-step-details">
81 <a href="https://github.com/dart-lang/dart-tutorials-samples/archive/master.zip" >
82 Download
83 </a>
84 the sample code.
85 Unzip the ZIP file.
86 </div>
87
88 #### <i class="icon-anchor"> </i> Open the directory.
89
90 <div class="trydart-step-details" markdown="1">
91 In Dart Editor,
92 open the `piratebadge` directory from the ZIP file
93 with **File>Open Existing Folder...**.
94 </div>
95
96 <div class="row"> <div class="span7" markdown="1">
97
98 ![The files and directories in the piratebadge directory.](images/filesanddirs.p ng)
99
100 </div> <div class="span5" markdown="1">
101
102 <i class="icon-key"> </i> <strong> Key Information </strong>
103
104 * Dart web apps use the public `browser` package to run on a web page.
105 This project has all of the package dependencies set up for you
106 and the packages installed.
107 The packages directory, the `pubspec.yaml`, and `pubspec.lock` files are
108 all related to library dependencies.
109
110 * Several numbered directories contain the completed code for each step.
111 `1-blankbadge` contains the skeletal version of the app that you begin with.
112 `6-piratebadge_json` contains the final version of the app.
113
114 * The `piratebadge.css` file
115 provides the CSS styles for all steps of the app.
116 You don't change this file during this code lab.
117
118 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
119
120 </div> </div>
121
122 <hr>
123
124 ##Step 1: Run the skeleton app {#step-one}
125
126 In this step, you open the source files for the skeleton app,
127 familiarize yourself with the Dart and HTML code,
128 and run the app.
129
130 #### <i class="icon-anchor"> </i> Expand the 1-blankbadge directory.
131
132 <div class="trydart-step-details" markdown="1">
133 In Dart Editor, expand the `1-blankbadge` directory,
134 which contains two files, `piratebadge.html` and `piratebadge.dart`.
135 </div>
136
137 #### <i class="icon-anchor"> </i> Open the files.
138
139 <div class="trydart-step-details" markdown="1">
140 Open both files by double-clicking each filename in Dart Editor.
141 </div>
142
143 #### <i class="icon-anchor"> </i> Review the code
144
145 <div class="trydart-step-details" markdown="1">
146 Get familiar with the HTML and the Dart code for the skeleton version of the app .
147 The interesting bits are highlighted below.
148 </div>
149
150 <div class="trydart-step-details" markdown="1">
151 ##### piratebadge.html
152 </div>
153
154 <div class="row"> <div class="span7">
155
156 <div class="trydart-step-details" markdown="1">
157 {% prettify html%}
158 <html>
159 <head>
160 <meta charset="utf-8">
161 <title>Pirate badge</title>
162 <link rel="stylesheet" href="../piratebadge.css">
163 </head>
164 <body>
165 <h1>Pirate badge</h1>
166
167 <div class="widgets">
168 [[highlight]]<span>TO DO: Put the UI widgets here.</span>[[/highlight]]
169 </div>
170 <div class="outer">
171 <div class="boilerplate">
172 Arrr! Me name is
173 </div>
174 <div class="name">
175 [[highlight]]<span id="badgeName"> </span>[[/highlight]]
176 </div>
177 </div>
178
179 [[highlight]]<script type="application/dart" src="piratebadge.dart"></script >[[/highlight]]
180 [[highlight]]<script src="packages/browser/dart.js"></script>[[/highlight]]
181 </body>
182 </html>
183 {% endprettify %}
184 </div>
185
186 </div> <div class="span5" markdown="1">
187
188 <i class="icon-key"> </i> <strong> Key Information </strong>
189
190 * During the code lab,
191 all the changes you make to `piratebadge.html` are within
192 the &lt;div&gt; element identified with the class `widgets`.
193
194 * The &lt;span&gt; element with the ID `badgeName`
195 is programmatically updated by the Dart code
sethladd 2013/10/23 21:15:06 you don't show the updating here. How about "is us
196 based on user input.
197
198 * The `piratebadge.dart` script provides the main program for the app.
199
200 * The `packages/browser/dart.js` script is a bootstrap script
201 that takes care of turning on the Dart VM,
202 as well as compatibility with non-Dart browsers.
203
204 </div> </div>
205
206 <div class="trydart-step-details" markdown="1">
207 ##### piratebadge.dart
208 </div>
209
210 <div class="row"> <div class="span7" markdown="1">
211
212 <div class="trydart-step-details" markdown="1">
213 {% prettify dart %}
214 [[highlight]]void main() {
215 // Your app starts here.
216 }
217 [[/highlight]]
218 {% endprettify %}
219 </div>
220
221 </div> <div class="span5" markdown="1">
222
223 * This file is included in the HTML file
sethladd 2013/10/23 21:15:06 it's not included, it's referenced by the main HTM
224 with the &lt;script&gt; tag.
225
226 * The `main()` function is a top-level function.
227 Dart calls this function when your app starts.
228
229 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
230 </div> </div>
231
232 #### <i class="icon-anchor"> </i> Run the app.
233
234 <div class="trydart-step-details" markdown="1">
235 To run the app in Dart Editor, select `piratebadge.html`
236 and click the Run button
237 <img src="images/run.png" width="16" height="16"
238 alt="Run button">.
239
240 You should see a TO DO comment on the left
241 and a red and white name badge on the right.
242 </div>
243
244 <div class="trydart-step-details" markdown="1">
245 <iframe class="running-app-frame"
246 style="height:220px;width:530px;"
247 src="examples/1-blankbadge/piratebadge.html">
248 </iframe>
249 </div>
250
251 <hr>
252
253 ##Step 2: Add an input field {#step-two}
254
255 In this step, you add an input field to the app.
256 As you type into the text field,
257 the Dart code updates the badge from the value of the text field.
258
259 #### <i class="icon-anchor"> </i> Try it!
260
261 <div class="trydart-step-details" markdown="1">
262 Type in the input field.
263
264 <iframe class="running-app-frame"
265 style="height:220px;width:530px;"
266 src="examples/2-inputnamebadge/piratebadge.html">
267 </iframe>
268 </div>
269
270 #### <i class="icon-anchor"> </i> Edit piratebadge.html.
271
272 <div class="row"> <div class="span7" markdown="1">
273
274 <div class="trydart-step-details" markdown="1">
275
276 Add the &lt;input&gt; tag to the HTML code
277 within the `widgets` &lt;div&gt;.
278
279 {% prettify html %}
280 ...
281 <div class="widgets">
282 [[highlight]] <div>
283 <input type="text" id="inputName">
284 </div>[[/highlight]]
285 </div>
286 ...
287 {% endprettify %}
288 </div>
289
290 </div> <div class="span5" markdown="1">
291
292 <i class="icon-key"> </i> <strong> Key Information </strong>
293
294 * The ID for the input element is `inputName`.
295 Dart uses CSS selectors, like this ID,
296 to get elements from the DOM.
297
298 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
299
300 </div> </div>
301
302 #### <i class="icon-anchor"> </i> Edit piratebadge.dart.
303
304 <div class="trydart-step-details" markdown="1">
305
306 Import the
307 <a href="https://api.dartlang.org/dart_html.html" target="_blank">dart:html</a>
308 library at the top of the file:
309
310 </div>
311
312 <div class="row"> <div class="span7">
313
314 <div class="trydart-step-details" markdown="1">
315
316 {% prettify dart %}
317 [[highlight]]import 'dart:html';[[/highlight]]
318 {% endprettify %}
319 </div>
320
321 </div> <div class="span5" markdown="1">
322
323 * This imports all classes and other resources from dart:html,
324 which provides HTML elements and access to the DOM.
325
326 </div> </div>
327
328 <div class="trydart-step-details" markdown="1">
329
330 <hr>
331
332 Register a function to handle input events on the input field.
333 </div>
334
335 <div class="row"> <div class="span7">
336
337 <div class="trydart-step-details" markdown="1">
338
339 {% prettify dart %}
340 void main() {
341 [[highlight]] query('#inputName').onInput.listen(updateBadge);[[/highlight]]
342 }
343 {% endprettify %}
344 </div>
345
346 </div> <div class="span5" markdown="1">
347
348 * The `query()` function, defined in
349 dart:html, gets an element from the DOM.
350 Here, the code uses the ID `#inputName`
351 to specify the input field.
352
353 * `onInput` registers an event handler for input events.
354
355 * An input event occurs when the user presses a key.
356
357 * You can use either single or double quotes to create a string.
358
359 </div> </div>
360
361 <div class="trydart-step-details" markdown="1">
362
363 <hr>
364
365 Implement the event handler as a top-level function.
366 </div>
367
368 <div class="row"> <div class="span7">
369
370 <div class="trydart-step-details" markdown="1">
371
372 {% prettify dart %}
373 [[highlight]]void updateBadge(Event e) {
374 query('#badgeName').text = (e.target as InputElement).value;
375 }[[/highlight]]
376 {% endprettify %}
377 </div>
378
379 </div> <div class="span5" markdown="1">
380
381 * This function sets the text of the `badgeName` element from the value of the i nput field.
382
383 * The `updateBadge()` function is an event handler based on its signature.
384
385 * The element that generated the event, the input field, is `e.target`.
386
387 * The `as` keyword typecasts `e.target` to an
388 <a href="https://api.dartlang.org/dart_html/InputElement.html" target="_blank">I nputElement</a>
389 to reference its value field.
390
391 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
392
393 </div> </div>
394
395 <hr>
396
397 ##Step 3: Add a button {#step-three}
398
399 In this step, you add a button to the app.
400 The button is enabled when the text field contains no text.
401 When the user clicks the button,
402 the app puts the name `Anne Bonney` on the badge.
403
404 #### Try it!
405
406 <div class="trydart-step-details" markdown="1">
407 Type in the input field.
408 Remove the text from the input field.
409 Click the button.
410 </div>
411
412 <div class="trydart-step-details">
413 <iframe class="running-app-frame"
414 style="height:220px;width:530px;"
415 src="examples/3-buttonbadge/piratebadge.html">
416 </iframe>
417 </div>
418
419 #### <i class="icon-anchor"> </i> Edit piratebadge.html.
420
421 <div class="trydart-step-details" markdown="1">
422 Add the &lt;button&gt; tag below the input field.
423 </div>
424
425 <div class="row"> <div class="span7">
426
427 <div class="trydart-step-details">
428 {% prettify html %}
429 ...
430 <div class="widgets">
431 <div>
432 <input type="text" id="inputName">
433 </div>
434 [[highlight]] <div>
435 <button id="generateButton">Generate badge</button>
436 </div>[[/highlight]]
437 </div>
438 ...
439 {% endprettify %}
440 </div>
441
442 </div> <div class="span5" markdown="1">
443
444 <i class="icon-key"> </i> <strong> Key Information </strong>
445
446 * The button has the ID `generateButton` so
447 the Dart code can get the element.
448
449 * The Dart code changes the button dynamically based on user input.
450
451 </div> </div>
452
453 #### <i class="icon-anchor"> </i> Edit piragebadge.dart.
454
455 <div class="trydart-step-details" markdown="1">
456 Below the import, declare a top-level variable to hold the
457 <a href="https://api.dartlang.org/dart_html/ButtonElement.html" target="_blank"> ButtonElement</a>.
458 </div>
459
460 <div class="row"> <div class="span7">
461
462 <div class="trydart-step-details">
463 {% prettify dart %}
464 import `dart:html`;
465
466 [[highlight]]ButtonElement genButton;[[/highlight]]
467 {% endprettify %}
468 </div>
469
470 </div> <div class="span5" markdown="1">
471
472 * Top-level variables are names at the library level.
473
474 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
475
476 </div> </div>
477
478 <div class="trydart-step-details" markdown="1">
479
480 <hr>
481
482 Wire up the button with an event handler.
483 </div>
484
485 <div class="row"> <div class="span7">
486
487 <div class="trydart-step-details">
488 {% prettify dart %}
489 void main() {}
490 query('#inputName').onInput.listen(updateBadge);
491 [[highlight]]genButton = query('#generateButton')
492 ..onClick.listen(generateBadge)[[/highlight]]
493 }
494 {% endprettify %}
495 </div>
496
497 </div> <div class="span5" markdown="1">
498
499 * `onClick` registers a mouse click handler.
500
501 * The cascade operator (`..`) allows you to perform multiple
502 operations on the members of a single object.
503
504 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
505
506 </div> </div>
507
508 <div class="trydart-step-details" markdown="1">
509
510 <hr>
511
512 Add a top-level setter that changes the name on the badge.
513 </div>
514
515 <div class="row"> <div class="span7">
516
517 <div class="trydart-step-details">
518 {% prettify dart %}
519 [[highlight]]set badgeName(String newName) {
520 query('#badgeName').text = newName;
521 } [[/highlight]]
522 {% endprettify %}
523 </div>
524
525 </div> <div class="span5" markdown="1">
526
527 * Setters are special methods that provide write access to an object’s propertie s.
528
529 * Here the setter updates the HTML page with a new name.
530
531 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
532
533 </div> </div>
534
535 <div class="trydart-step-details" markdown="1">
536
537 <hr>
538
539 Implement the click handler for the button.
540 </div>
541
542 <div class="row"> <div class="span7">
543
544 <div class="trydart-step-details">
545 {% prettify dart %}
546 [[highlight]]void generateBadge(Event e) {
547 badgeName = 'Anne Bonney';
548 }[[/highlight]]
549 {% endprettify %}
550 </div>
551
552 </div> <div class="span5" markdown="1">
553
554 * This function calls the setter to set the badge name to `Anne Bonney`.
555 Note that the call to a setter looks like a field assignment.
556
557 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
558
559 </div> </div>
560
561 <div class="trydart-step-details" markdown="1">
562
563 <hr>
564
565 Replace the contents of the `updateBadge()` function
566 with this code.
567 </div>
568
569 <div class="row"> <div class="span7">
570
571 <div class="trydart-step-details">
572 {% prettify dart %}
573 void updateBadge(Event e) {
574 [[highlight]] String inputName = (e.target as InputElement).value;
575
576 badgeName = inputName;
577 if (inputName.trim().isEmpty) {
578 genButton..disabled = false
579 ..text = 'Generate badge';
580 } else {
581 genButton..disabled = true
582 ..text = 'Arrr! Remove the text!';
583 }[[/highlight]]
584 }
585 {% endprettify %}
586 </div>
587 </div> <div class="span5" markdown="1">
588
589 * The
590 <a href="https://api.dartlang.org/dart_core/String.html" target="_blank">String< /a>
591 class has useful functions and properties for dealing with strings,
592 such as `trim()` and `isEmpty`.
593
594 * String comes from the
595 <a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a>
596 library, which is automatically imported into every Dart program.
597
598 * Here, you see the cascade operator in action again.
599
600 * This code calls the setter to set the badge name.
601
602 * Dart has common programming language constructs like `if`-`else`.
603
604 </div></div>
605
606 <hr>
607
608 ##Step 4: Create a PirateName class {#step-four}
609
610 In this step, you change only the Dart code.
611 You create a class to represent a pirate name.
612 When created, an instance of this class
613 randomly selects a name and appellation from a list,
614 or optionally you can provide a name
615 and an appellation to the constructor.
616
617 #### Try it!
618
619 <div class="trydart-step-details" markdown="1">
620 Type in the input field.
621 Remove the text from the input field.
622 Click the button.
623 </div>
624
625 <div class="trydart-step-details">
626 <iframe class="running-app-frame"
627 style="height:220px;width:530px;"
628 src="examples/4-classbadge/piratebadge.html">
629 </iframe>
630 </div>
631
632 #### <i class="icon-anchor"> </i> Edit piratebadge.dart.
633
634 <div class="trydart-step-details" markdown="1">
635 Add an import to the top of the file.
636 </div>
637
638 <div class="row"> <div class="span7">
639
640 <div class="trydart-step-details">
641 {% prettify dart %}
642 import 'dart:html';
643 import 'dart:math' show Random;
644 {% endprettify %}
645 </div>
646 </div> <div class="span5" markdown="1">
647
648 <i class="icon-key"> </i> <strong> Key Information </strong>
649
650 * Using the `show` keyword,
651 you can import just the classes you need.
652
653 * <a href="https://api.dartlang.org/dart_math/Random.html" target="_blank">Rando m</a>
654 provides a random number generator.
655
656 </div></div>
657
658 <div class="trydart-step-details" markdown="1">
659
660 <hr>
661
662 Add a class declaration to the bottom of the file.
663 </div>
664
665 <div class="row"> <div class="span7">
666
667 <div class="trydart-step-details">
668 {% prettify dart %}
669 class PirateName {
670 ...
671 }
672 {% endprettify %}
673 </div>
674 </div> <div class="span5" markdown="1">
675
676 * The class declaration provides the class name.
677
678 </div></div>
679
680 <div class="trydart-step-details" markdown="1">
681
682 <hr>
683
684 Create a class-level Random object.
685 </div>
686
687 <div class="row"> <div class="span7">
688
689 <div class="trydart-step-details">
690 {% prettify dart %}
691 class PirateName {
692 [[highlight]]static final Random indexGen = new Random();[[/highlight]]
693 }
694 {% endprettify %}
695 </div>
696 </div> <div class="span5" markdown="1">
697
698 * `static` defines a class-level field. That is,
699 the random number generator is shared with all
700 instances of this class.
701
702 * Use `new` to call a constructor.
703
704 </div></div>
705
706 <div class="trydart-step-details" markdown="1">
707
708 <hr>
709
710 Add two instance variables to class,
711 one for the first name and one for the appellation.
712 </div>
713
714 <div class="row"> <div class="span7">
715
716 <div class="trydart-step-details">
717 {% prettify dart %}
718 class PirateName {
719 ...
720 [[highlight]] String _firstName;
721 String _appellation;[[/highlight]]
722 }
723 {% endprettify %}
724 </div>
725 </div> <div class="span5" markdown="1">
726
727 * Private variables start with underscore (`_`).
728
729 </div></div>
730
731 <div class="trydart-step-details" markdown="1">
732
733 <hr>
734
735 Create two static lists within the class
736 that provide a small collection of names and appellations to choose from.
737 </div>
738
739 <div class="row"> <div class="span7">
740
741 <div class="trydart-step-details">
742 {% prettify dart %}
743 class PirateName {
744 ...
745 [[highlight]] static final List names = [
746 'Anne', 'Mary', 'Jack', 'Morgan', 'Roger',
747 'Bill', 'Ragnar', 'Ed', 'John', 'Jane' ];
748 static final List appellations = [
749 'Black','Damned', 'Jackal', 'Red', 'Stalwart', 'Axe',
750 'Young', 'Old', 'Angry', 'Brave', 'Crazy', 'Noble'];[[/highlight]]
751 }
752 {% endprettify %}
753 </div>
754 </div> <div class="span5" markdown="1">
755
756 * `final` variables cannot change.
757
758 * Lists are built into the language.
759 These lists are created using list literals.
760
761 * The
762 <a href="https://api.dartlang.org/dart_core/List.html" target="_blank">List</a>
763 class provides the API for lists.
764
765 </div></div>
766
767
768 <div class="trydart-step-details" markdown="1">
769
770 <hr>
771
772 Provide a constructor for the class.
773 </div>
774
775 <div class="row"> <div class="span7">
776
777 <div class="trydart-step-details">
778 {% prettify dart %}
779 class PirateName {
780 ...
781 [[highlight]] PirateName({String firstName, String appellation}) {
782 if (firstName == null) {
783 _firstName = names[indexGen.nextInt(names.length)];
784 } else {
785 _firstName = firstName;
786 }
787 if (appellation == null) {
788 _appellation = appellations[indexGen.nextInt(appellations.length)];
789 } else {
790 _appellation = appellation;
791 }
792 }[[/highlight]]
793 }
794 {% endprettify %}
795 </div>
796
797 </div> <div class="span5" markdown="1">
798
799 * Constructors have the same name as the class.
800
801 * Optional parameters are enclosed in curly brackets (`{` and `}`).
802
803 * The `nextInt()` function gets a new random integer
804 from the random number generator.
805
806 * Square brackets (`[` and `]`) are operators to index into a list.
807
808 * The `length` property returns the length of a list.
809
810 * The code uses a random number as an index into the list.
811
812 </div> </div>
813
814 <div class="trydart-step-details" markdown="1">
815
816 <hr>
817
818 Provide a getter for the pirate name.
819 </div>
820
821 <div class="row"> <div class="span7">
822
823 <div class="trydart-step-details">
824 {% prettify dart %}
825 class PirateName {
826 ...
827 [[highlight]] String get pirateName => '$_firstName the $_appellation';[[/highl ight]]
828 }
829 {% endprettify %}
830 </div>
831
832 </div><div class="span5" markdown="1">
833
834 * Getters are special methods that provide read access to an object’s properties .
835
836 </div></div>
837
838 <div class="trydart-step-details" markdown="1">
839
840 <hr>
841
842 Modify the setter `badgeName()` to use a PirateName instead of a String:
843 </div>
844
845 <div class="row"> <div class="span7">
846
847 <div class="trydart-step-details">
848 {% prettify dart %}
849 set badgeName([[highlight]]PirateName newName[[/highlight]]) {
850 query('#badgeName').text = [[highlight]]newName.pirateName[[/highlight]];
851 }
852 {% endprettify %}
853 </div>
854
855 </div><div class="span5" markdown="1">
856
857 * This code calls the getter to get the PirateName as a string.
858
859 </div></div>
860
861 <div class="trydart-step-details" markdown="1">
862
863 <hr>
864
865 Change `updateBadge()` to generate a PirateName based on the input field value.
866 </div>
867
868 <div class="row"> <div class="span7">
869
870 <div class="trydart-step-details">
871 {% prettify dart %}
872 void updateBadge(Event e) {
873 String inputName = (e.target as InputElement).value;
874
875 [[highlight]]badgeName = new PirateName(firstName: inputName);[[/highlight]]
876 ...
877 }
878 {% endprettify %}
879 </div>
880
881 </div><div class="span5" markdown="1">
882
883 * The call to the constructor provides a value for one optional parameter.
884
885 </div></div>
886
887 <div class="trydart-step-details" markdown="1">
888
889 <hr>
890
891 Change `generateBadge()` to generate a PirateName instead of using `Anne Bonney` .
892 </div>
893
894 <div class="row"> <div class="span7">
895
896 <div class="trydart-step-details">
897 {% prettify dart %}
898 void generateBadge(Event e) {
899 [[highlight]]badgeName = new PirateName();[[/highlight]]
900 }
901 {% endprettify %}
902 </div>
903
904 </div><div class="span5" markdown="1">
905
906 * The call to the constructor passes no parameters.
907
908 </div></div>
909
910 ##Step 5: Save to local storage {#step-five}
911
912 In this step, you give the app some persistence
913 by saving the badge name to local storage each time it changes.
914 When you restart the app,
915 it initializes the badge from the saved name.
916
917 #### Try it!
918
919 <div class="trydart-step-details" markdown="1">
920 Click the button, then kill the app by closing this window.
921 Open this page up in a new window.
922 </div>
923
924 <div class="trydart-step-details">
925 <iframe class="running-app-frame"
926 style="height:220px;width:530px;"
927 src="examples/5-localbadge/piratebadge.html">
928 </iframe>
929 </div>
930
931 #### <i class="icon-anchor"> </i> Edit piratebadge.dart.
932
933 <div class="trydart-step-details" markdown="1">
934 Import the JSON converter from the
935 <a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:conver t</a>
936 library.
937 </div>
938
939 <div class="row"> <div class="span7">
940
941 <div class="trydart-step-details">
942 {% prettify dart %}
943 import 'dart:html';
944 import 'dart:math' show Random;
945 [[highlight]]
946 import 'dart:convert' show JSON;[[/highlight]]
947 {% endprettify %}
948 </div>
949
950 </div> <div class="span5" markdown="1">
951
952 <i class="icon-key"> </i> <strong> Key Information </strong>
953
954 * `JSON` provides convenient access to the most common JSON use cases.
955
956 </div> </div>
957
958 <div class="trydart-step-details" markdown="1">
959
960 <hr>
961
962 Add a new constructor to the PirateName class.
963 </div>
964
965 <div class="row"> <div class="span7">
966
967 <div class="trydart-step-details">
968 {% prettify dart %}
969 class PirateName {
970 ...
971 [[highlight]] PirateName.fromJSON(String jsonString) {
972 Map storedName = JSON.decode(jsonString);
973 _firstName = storedName['f'];
974 _appellation = storedName['a'];
975 }[[/highlight]]
976 }
977 {% endprettify %}
978 </div>
979
980 </div> <div class="span5" markdown="1">
981
982 * The constructor creates a new PirateName instance from a JSON-encoded string.
983
984 * `PirateName.fromJson` is a named constructor.
985
986 * `JSON.decode()` parses a JSON string and creates Dart objects from it.
987
988 * The pirate name is decoded into a
989 <a href="https://api.dartlang.org/dart_core/Map.html" target="_blank">Map</a>
990 object.
991
992 </div> </div>
993
994 <div class="trydart-step-details" markdown="1">
995
996 <hr>
997
998 Add a getter to the PirateName class
999 that encodes a pirate name in a JSON string.
1000 </div>
1001
1002 <div class="row"> <div class="span7">
1003
1004 <div class="trydart-step-details">
1005 {% prettify dart %}
1006 class PirateName {
1007 ...
1008 [[highlight]]String toJsonString() => '{ "f": "$_firstName", "a": "$_appellati on" } ';[[/highlight]]
1009 }
1010 {% endprettify %}
1011 </div>
1012
1013 </div> <div class="span5" markdown="1">
1014
1015 * The getter formats the JSON string using the map format.
1016
1017 </div> </div>
1018
1019
1020 <div class="trydart-step-details" markdown="1">
1021
1022 <hr>
1023
1024 Declare a top-level boolean variable.
1025 </div>
1026
1027 <div class="row"> <div class="span7">
1028
1029 <div class="trydart-step-details">
1030 {% prettify dart %}
1031 [[highlight]]final String TREASUREKEY = 'pirateName';[[/highlight]]
1032 {% endprettify %}
1033 </div>
1034
1035 </div> <div class="span5" markdown="1">
1036
1037 * This string is a key to the local storage,
1038 hopefully unique.
1039
1040 </div> </div>
1041
1042 <div class="trydart-step-details" markdown="1">
1043
1044 <hr>
1045
1046 Save the pirate name when the badge name changes.
1047 </div>
1048
1049 <div class="row"> <div class="span7">
1050
1051 <div class="trydart-step-details">
1052 {% prettify dart %}
1053 set badgeName(PirateName newName) {
1054 query('#badgeName').text = newName.pirateName;
1055 [[highlight]]window.localStorage[TREASUREKEY] = newName.toJsonString();[[/high light]]
1056 }
1057 {% endprettify %}
1058 </div>
1059
1060 </div> <div class="span5" markdown="1">
1061
1062 * Local storage is provided by the browser's window.
1063
1064 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
1065
1066 </div> </div>
1067
1068 <div class="trydart-step-details" markdown="1">
1069
1070 <hr>
1071
1072 Add a top-level getter.
1073 </div>
1074
1075 <div class="row"> <div class="span7">
1076
1077 <div class="trydart-step-details">
1078 {% prettify dart %}
1079 [[highlight]]PirateName get pirateNameFromStorage {
1080 String storedName = window.localStorage[TREASUREKEY];
1081 if (storedName != null) {
1082 return new PirateName.fromJSON(storedName);
1083 } else {
1084 return null;
1085 }
1086 }[[/highlight]]
1087 {% endprettify %}
1088 </div>
1089
1090 </div> <div class="span5" markdown="1">
1091
1092 * The getter retrieves the pirate name from local storage
1093 and creates a PirateName object from it.
1094
1095 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
1096
1097 </div> </div>
1098
1099 <div class="trydart-step-details" markdown="1">
1100 <hr>
1101 Call the getter from the `main()` function.
1102 </div>
1103
1104 <div class="row"> <div class="span7">
1105
1106 <div class="trydart-step-details">
1107 {% prettify dart %}
1108 void main() {
1109 ...
1110 [[highlight]]badgeName = pirateNameFromStorage;[[/highlight]]
1111 }
1112 {% endprettify %}
1113 </div>
1114
1115 </div> <div class="span5" markdown="1">
1116
1117 * Initialize the badge name from local storage.
1118
1119 &nbsp; {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %}
1120
1121 </div> </div>
1122
1123 ##Step 6: Read names from JSON-encoded file {#step-six}
1124
1125 In this step, you change the PirateName class to get
1126 the list of names and appellations from a JSON file.
1127 This gives you a chance to add more names and
1128 appellations to the program.
1129
1130 #### Try it!
1131
1132 <div class="trydart-step-details">
1133 The final app is running here.
1134 </div>
1135
1136 <div class="trydart-step-details">
1137 <iframe class="running-app-frame"
1138 style="height:220px;width:530px;"
1139 src="examples/6-piratebadge_json/piratebadge.html">
1140 </iframe>
1141 </div>
1142
1143 #### <i class="icon-anchor"> </i> Create piratenames.json.
1144
1145 <div class="trydart-step-details" markdown="1">
1146 Create a JSON encoded file named `piratenames.json`.
1147 </div>
1148
1149 <div class="row"> <div class="span7">
1150
1151 <div class="trydart-step-details">
1152 {% prettify dart %}
1153 { "names": [ "Anne", "Bette", "Cate", "Dawn",
1154 "Elise", "Faye", "Ginger", "Harriot",
1155 "Izzy", "Jane", "Kaye", "Liz",
1156 "Maria", "Nell", "Olive", "Pat",
1157 "Queenie", "Rae", "Sal", "Tam",
1158 "Uma", "Violet", "Wilma", "Xana",
1159 "Yvonne", "Zelda",
1160 "Abe", "Billy", "Caleb", "Davie",
1161 "Eb", "Frank", "Gabe", "House",
1162 "Icarus", "Jack", "Kurt", "Larry",
1163 "Mike", "Nolan", "Oliver", "Pat",
1164 "Quib", "Roy", "Sal", "Tom",
1165 "Ube", "Val", "Walt", "Xavier",
1166 "Yvan", "Zeb"],
1167 "appellations": [ "Awesome", "Black", "Captain", "Damned",
1168 "Even", "Fighter", "Great", "Hearty",
1169 "Irate", "Jackal", "King", "Lord",
1170 "Mighty", "Noble", "Old", "Powerful",
1171 "Quick", "Red", "Stalwart", "Tank",
1172 "Ultimate", "Vicious", "Wily", "aXe",
1173 "Young", "Zealot",
1174 "Angry", "Brave", "Crazy", "Damned",
1175 "Eager", "Fool", "Greedy", "Hated",
1176 "Idiot", "Jinxed", "Kind", "Lame",
1177 "Maimed", "Naked", "Old", "Pale",
1178 "Queasy", "Rat", "Sandy", "Tired",
1179 "Ugly", "Vile", "Weak", "Xeric",
1180 "Yellow", "Zesty"]}
1181 {% endprettify %}
1182 </div>
1183
1184 </div> <div class="span5" markdown="1">
1185
1186 <i class="icon-key"> </i> <strong> Key Information </strong>
1187
1188 * Put the file alongside the Dart and HTML files for the app.
1189
1190 * The file contains the code for a map
1191 that contains two lists that each contain strings.
1192
1193 </div> </div>
1194
1195 #### <i class="icon-anchor"> </i> Edit piratebadge.html.
1196
1197 <div class="trydart-step-details" markdown="1">
1198 Disable the input field and the button.
1199 </div>
1200
1201 <div class="row"> <div class="span7">
1202
1203 <div class="trydart-step-details">
1204 {% prettify html %}
1205 ...
1206 <div>
1207 <input type="text" id="inputName" [[highlight]]disabled[[/highlight]]>
1208 </div>
1209 <div>
1210 <button id="generateButton" [[highlight]]disabled[[/highlight]]>Generate bad ge</button>
1211 </div>
1212 ...
1213 {% endprettify %}
1214 </div>
1215
1216 </div> <div class="span5" markdown="1">
1217
1218
1219 * The Dart code enables the text field and
1220 the button after the pirate names are successfully read from
1221 the JSON file.
1222
1223 </div> </div>
1224
1225 #### <i class="icon-anchor"> </i> Edit piratebadge.dart.
1226
1227 <div class="trydart-step-details" markdown="1">
1228
1229 Add an import to the top of the file.
1230 </div>
1231
1232 <div class="row"> <div class="span7">
1233
1234 <div class="trydart-step-details">
1235 {% prettify dart %}
1236 import 'dart:html';
1237 import 'dart:math' show Random;
1238 import 'dart:convert' show JSON;
1239
1240 [[highlight]]import 'dart:async' show Future;[[/highlight]]
1241 {% endprettify %}
1242 </div>
1243
1244 </div> <div class="span5" markdown="1">
1245
1246 * The
1247 <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a >
1248 library provides for asynchronous programming.
1249
1250 * A <a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Fu ture</a>
1251 provides a way to get a value in the future.
1252
1253 </div> </div>
1254
1255 <div class="trydart-step-details" markdown="1">
1256
1257 <hr>
1258 Replace the list literals with these static empty lists:
1259 </div>
1260
1261 <div class="row"> <div class="span7">
1262
1263 <div class="trydart-step-details">
1264 {% prettify dart %}
1265 class PirateName {
1266 ...
1267 [[highlight]]static List<String> names = [];
1268 static List<String> appellations = [];[[/highlight]]
1269 ...
1270 }
1271 {% endprettify %}
1272 </div>
1273
1274 </div> <div class="span5" markdown="1">
1275
1276 * `[]` is equivalent to `new List()`.
1277
1278 </div> </div>
1279
1280 <div class="trydart-step-details" markdown="1">
1281
1282 <hr>
1283
1284 Add two static functions to the PirateName class:
1285 </div>
1286
1287 <div class="row"> <div class="span7">
1288
1289 <div class="trydart-step-details">
1290 {% prettify dart %}
1291 class PirateName {
1292 ...
1293
1294 [[highlight]]static Future readyThePirates() {
1295 var path = 'piratenames.json';
1296 return HttpRequest.getString(path)
1297 .then(_parsePirateNamesFromJSON);
1298 }
1299
1300 static _parsePirateNamesFromJSON(String jsonString) {
1301 Map pirateNames = JSON.decode(jsonString);
1302 names = pirateNames['names'];
1303 appellations = pirateNames['appellations'];
1304 }[[/highlight]]
1305 }
1306 {% endprettify %}
1307 </div>
1308
1309 </div> <div class="span5" markdown="1">
1310
1311 * <a href="https://api.dartlang.org/dart_html/HttpRequest.html" target="_blank"> HttpRequest</a>
1312 is a utilify for retrieving data from a URL.
1313
1314 * `getString()` is a convenience method for doing a simple
1315 GET request that returns a string.
1316
1317 * The code uses a
1318 <a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Future </a>
1319 to perform the GET asynchronously.
1320
1321 * The callback function for `.then()` is called when
1322 the Future completes successfully.
1323
1324 * When the Future completes successfully,
1325 the pirate names are read from the JSON file.
1326
1327 * Futures are infectious.
1328 `readyThePirates` must return the Future so the main program can handle it.
1329
1330 </div> </div>
1331
1332 <div class="trydart-step-details" markdown="1">
1333 <hr>
1334 Modify the `main()` function to look like this:
1335 </div>
1336
1337 <div class="row"> <div class="span7">
1338
1339 <div class="trydart-step-details">
1340 {% prettify dart %}
1341 void main() {
1342 InputElement inputField = query('#inputName')
1343 ..onInput.listen(updateBadge);
1344 genButton = query('#generateButton')
1345 ..onClick.listen(generateBadge);
1346
1347 badgeNameElement = query('#badgeName');
1348
1349 PirateName.readyThePirates()
1350 .then((_) {
1351 inputField.disabled = false; //enable
1352 genButton.disabled = false; //enable
1353 badgeName = pirateNameFromStorage;
1354 })
1355 .catchError((arrr) {
1356 print('Error initializing pirate names: $arrr');
1357 badgeNameElement.text = 'Arrr! No names.';
1358 });
1359 }
1360 {% endprettify %}
1361 </div>
1362
1363 </div> <div class="span5" markdown="1">
1364
1365 * When the Future successfully completes,
1366 the `then()` callback function is called.
1367
1368 * The callback function enables the UI
1369 and gets the stored name.
1370
1371 * If the Future encounters an error
1372 the `catchError` callback function is called
1373 and the program displays an error message,
1374 leaving the UI disabled.
1375
1376 </div> </div>
1377
1378 ##Step 7: What next? {#step-seven}
1379
1380 #### <i class="icon-anchor"> </i> Check out the samples.
1381
1382 <div class="trydart-step-details" markdown="1">
1383
1384 Run some Dart programs online and check out the source code
1385 on our [Samples page](/samples/).
1386 </div>
1387
1388 #### <i class="icon-anchor"> </i> Read the tutorials.
1389
1390 <div class="trydart-step-details" markdown="1">
1391 Learn more about Dart from
1392 the [Dart tutorials](/docs/tutorials/).
1393 </div>
OLDNEW
« no previous file with comments | « src/site/articles/trydart/images/run.png ('k') | src/site/articles/trydart/trydart.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698