OLD | NEW |
(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: ["/codelabs/darrrt/darrrt.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 The sample app provides a brief look at some Dart language and library features. |
| 26 This code lab assumes that you have some programming experience. |
| 27 |
| 28 <strong>Build this app!</strong> |
| 29 |
| 30 <iframe class="running-app-frame" |
| 31 style="height:220px;width:530px;" |
| 32 src="examples/6-piratebadge_json/piratebadge.html"> |
| 33 </iframe> |
| 34 |
| 35 <hr> |
| 36 |
| 37 ## The Map |
| 38 |
| 39 * [Step 0: Set up](#set-up) |
| 40 * [Step 1: Run the skeleton app](#step-one) |
| 41 * [Step 2: Add an input field](#step-two) |
| 42 * [Step 3: Add a button](#step-three) |
| 43 * [Step 4: Create a class](#step-four) |
| 44 * [Step 5: Save to local storage](#step-five) |
| 45 * [Step 6: Read names from JSON file using HttpRequest](#step-six) |
| 46 * [Step 7: Go forth and learn more about Dart](#step-seven) |
| 47 |
| 48 |
| 49 <hr> |
| 50 |
| 51 ## Step 0: Set up {#set-up} |
| 52 |
| 53 In this step, you download Dart and get the sample code. |
| 54 |
| 55 |
| 56 #### <i class="icon-anchor"> </i> Get Dart. |
| 57 |
| 58 <div class="trydart-step-details" markdown="1"> |
| 59 If you haven't already done so, |
| 60 get the Dart download. |
| 61 Unzip the ZIP file, which creates a directory called `dart`. |
| 62 |
| 63 {% include downloads/_dart-editor.html %} |
| 64 |
| 65 <p markdown="1"> |
| 66 The Dart tools |
| 67 work in recent versions of |
| 68 {% include os-choices.html %} |
| 69 </p> |
| 70 </div> |
| 71 |
| 72 #### <i class="icon-anchor"> </i> Start the editor. |
| 73 |
| 74 <div class="trydart-step-details" markdown="1"> |
| 75 Go to the `dart` directory and double-click **DartEditor**. |
| 76 |
| 77 **Got questions? Having trouble?** Go to the |
| 78 [Troubleshooting Dart Editor](/tools/editor/troubleshoot.html) page. |
| 79 |
| 80 </div> |
| 81 |
| 82 #### <i class="icon-anchor"> </i> Get the sample code. |
| 83 |
| 84 <div class="trydart-step-details" markdown="1"> |
| 85 <a href="https://github.com/dart-lang/one-hour-codelab/archive/master.zip">Downl
oad</a> |
| 86 the sample code. |
| 87 Unzip the ZIP file, |
| 88 which creates a directory called `one-hour-codelab-master`. |
| 89 </div> |
| 90 |
| 91 #### <i class="icon-anchor"> </i> Open the one-hour-codelab-master sample. |
| 92 |
| 93 <div class="trydart-step-details" markdown="1"> |
| 94 In Dart Editor, |
| 95 use **File > Open Existing Folder...** |
| 96 to open the `one-hour-codelab-master` directory. |
| 97 </div> |
| 98 |
| 99 <div class="row"> <div class="span7" markdown="1"> |
| 100 |
| 101  |
| 102 |
| 103 </div> <div class="span5" markdown="1"> |
| 104 |
| 105 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 106 |
| 107 * The `packages` directory, as well as the `pubspec.yaml` and `pubspec.lock` fil
es are |
| 108 related to package dependencies. |
| 109 This project has all the dependencies set up for you. |
| 110 Dart Editor automatically installs the necessary packages. |
| 111 |
| 112 * Several numbered directories contain the completed code for each step. |
| 113 `1-blankbadge` contains the skeletal version of the app that you begin with. |
| 114 `6-piratebadge_json` contains the final version of the app. |
| 115 |
| 116 * The `piratebadge.css` file |
| 117 provides the CSS styles for all steps of the app. |
| 118 You don't change this file during this code lab. |
| 119 |
| 120 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 121 |
| 122 </div> </div> |
| 123 |
| 124 <hr> |
| 125 |
| 126 ##Step 1: Run the skeleton app {#step-one} |
| 127 |
| 128 In this step, you open the source files, |
| 129 familiarize yourself with the Dart and HTML code, |
| 130 and run the app. |
| 131 |
| 132 #### <i class="icon-anchor"> </i> Expand the 1-blankbadge directory. |
| 133 |
| 134 <div class="trydart-step-details" markdown="1"> |
| 135 In Dart Editor, expand the `1-blankbadge` directory |
| 136 by clicking the little arrow |
| 137  to the left of its name. |
| 138 The directory contains two files, `piratebadge.html` and `piratebadge.dart`. |
| 139 </div> |
| 140 |
| 141 #### <i class="icon-anchor"> </i> Open the files. |
| 142 |
| 143 <div class="trydart-step-details" markdown="1"> |
| 144 Open both files, `piratebadge.html` and `piratebadge.dart`, |
| 145 by double-clicking each filename in Dart Editor. |
| 146 </div> |
| 147 |
| 148 #### <i class="icon-anchor"> </i> Review the code. |
| 149 |
| 150 <div class="trydart-step-details" markdown="1"> |
| 151 Get familiar with the HTML and the Dart code for the skeleton version of the app
. |
| 152 </div> |
| 153 |
| 154 <div class="trydart-step-details" markdown="1"> |
| 155 ##### piratebadge.html |
| 156 </div> |
| 157 |
| 158 <div class="row"> <div class="span7"> |
| 159 |
| 160 <div class="trydart-step-details" markdown="1"> |
| 161 {% prettify html%} |
| 162 <html> |
| 163 <head> |
| 164 <meta charset="utf-8"> |
| 165 <title>Pirate badge</title> |
| 166 <link rel="stylesheet" href="../piratebadge.css"> |
| 167 </head> |
| 168 <body> |
| 169 <h1>Pirate badge</h1> |
| 170 |
| 171 [[highlight]]<div class="widgets">[[/highlight]] |
| 172 [[highlight]]TO DO: Put the UI widgets here.[[/highlight]] |
| 173 [[highlight]]</div>[[/highlight]] |
| 174 <div class="badge"> |
| 175 <div class="greeting"> |
| 176 Arrr! Me name is |
| 177 </div> |
| 178 <div class="name"> |
| 179 [[highlight]]<span id="badgeName"> </span>[[/highlight]] |
| 180 </div> |
| 181 </div> |
| 182 |
| 183 [[highlight]]<script type="application/dart" src="piratebadge.dart"></script
>[[/highlight]] |
| 184 [[highlight]]<script src="packages/browser/dart.js"></script>[[/highlight]] |
| 185 </body> |
| 186 </html> |
| 187 {% endprettify %} |
| 188 |
| 189 </div> |
| 190 <div class="trydart-filename">piratebadge.html</div> |
| 191 |
| 192 </div> <div class="span5" markdown="1"> |
| 193 |
| 194 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 195 |
| 196 * During this code lab, |
| 197 all the changes you make to `piratebadge.html` are within |
| 198 the <div> element identified with the class `widgets`. |
| 199 |
| 200 * In later steps, |
| 201 the <span> element with the ID `badgeName` |
| 202 is programmatically updated by the Dart code |
| 203 based on user input. |
| 204 |
| 205 * The `piratebadge.dart` script provides the main program for the app. |
| 206 |
| 207 * The `packages/browser/dart.js` script is a bootstrap script |
| 208 that takes care of turning on the Dart VM, |
| 209 as well as compatibility with non-Dart browsers. |
| 210 |
| 211 </div> </div> |
| 212 |
| 213 <div class="trydart-step-details" markdown="1"> |
| 214 ##### piratebadge.dart |
| 215 </div> |
| 216 |
| 217 <div class="row"> <div class="span7" markdown="1"> |
| 218 |
| 219 <div class="trydart-step-details" markdown="1"> |
| 220 {% prettify dart %} |
| 221 [[highlight]]void main() { |
| 222 // Your app starts here. |
| 223 } |
| 224 [[/highlight]] |
| 225 {% endprettify %} |
| 226 </div> |
| 227 <div class="trydart-filename">piratebadge.dart</div> |
| 228 |
| 229 </div> <div class="span5" markdown="1"> |
| 230 |
| 231 * This file is the main script for the app. |
| 232 It is referenced by a <script> tag in the `piratebadge.html` file. |
| 233 |
| 234 * The `main()` function is a top-level function. |
| 235 Dart calls this function when your app starts. |
| 236 |
| 237 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 238 </div> </div> |
| 239 |
| 240 #### <i class="icon-anchor"> </i> Run the app. |
| 241 |
| 242 <div class="trydart-step-details" markdown="1"> |
| 243 To run the app in Dart Editor, select `piratebadge.html` |
| 244 and click the Run button |
| 245 <img src="images/run.png" width="16" height="16" |
| 246 alt="Run button">. |
| 247 |
| 248  |
| 249 |
| 250 You should see a TO DO comment on the left |
| 251 and a red and white name badge on the right. |
| 252 </div> |
| 253 |
| 254 <div class="trydart-step-details" markdown="1"> |
| 255 <iframe class="running-app-frame" |
| 256 style="height:220px;width:530px;" |
| 257 src="examples/1-blankbadge/piratebadge.html"> |
| 258 </iframe> |
| 259 </div> |
| 260 |
| 261 <hr> |
| 262 |
| 263 ##Step 2: Add an input field {#step-two} |
| 264 |
| 265 <div class="trydart-note" markdown="1"> |
| 266 <strong>Note:</strong> Throughout this code lab, |
| 267 continue to edit the files in `1-blankbadge`. |
| 268 You can use the files in the other directories to compare to your code |
| 269 or to recover if you get off track. |
| 270 </div> |
| 271 |
| 272 In this step, you add an input field to the app. |
| 273 As the user types into the text field, |
| 274 the Dart code updates the badge from the value of the text field. |
| 275 |
| 276 #### <i class="icon-anchor"> </i> Edit piratebadge.html. |
| 277 |
| 278 <div class="row"> <div class="span7" markdown="1"> |
| 279 |
| 280 <div class="trydart-step-details" markdown="1"> |
| 281 |
| 282 Add the <input> tag to the HTML code |
| 283 within the `widgets` <div>. |
| 284 |
| 285 {% prettify html %} |
| 286 ... |
| 287 <div class="widgets"> |
| 288 [[highlight]] <div> |
| 289 <input type="text" id="inputName" maxlength="15"> |
| 290 </div>[[/highlight]] |
| 291 </div> |
| 292 ... |
| 293 {% endprettify %} |
| 294 </div> |
| 295 |
| 296 <div class="trydart-filename">piratebadge.html</div> |
| 297 |
| 298 </div> <div class="span5" markdown="1"> |
| 299 |
| 300 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 301 |
| 302 * The ID for the input element is `inputName`. |
| 303 Dart uses CSS selectors, like this ID, |
| 304 to get elements from the DOM. |
| 305 |
| 306 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 307 |
| 308 </div> </div> |
| 309 |
| 310 #### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
| 311 |
| 312 <div class="trydart-step-details" markdown="1"> |
| 313 |
| 314 Import the `dart:html` |
| 315 library at the top of the file |
| 316 (below the copyright). |
| 317 |
| 318 </div> |
| 319 |
| 320 <div class="row"> <div class="span7"> |
| 321 |
| 322 <div class="trydart-step-details" markdown="1"> |
| 323 |
| 324 {% prettify dart %} |
| 325 [[highlight]]import 'dart:html';[[/highlight]] |
| 326 {% endprettify %} |
| 327 </div> |
| 328 |
| 329 <div class="trydart-filename">piratebadge.dart</div> |
| 330 |
| 331 </div> <div class="span5" markdown="1"> |
| 332 |
| 333 * This imports all classes and other resources from dart:html, |
| 334 which provides HTML elements and access to the DOM. |
| 335 |
| 336 * Dart Editor helpfully warns you that the import is unused. |
| 337 Don't worry about it. You'll fix it in the next step. |
| 338 |
| 339 </div> </div> |
| 340 |
| 341 <div class="trydart-step-details" markdown="1"> |
| 342 |
| 343 <hr> |
| 344 |
| 345 Register a function to handle input events on the input field. |
| 346 </div> |
| 347 |
| 348 <div class="row"> <div class="span7"> |
| 349 |
| 350 <div class="trydart-step-details" markdown="1"> |
| 351 |
| 352 {% prettify dart %} |
| 353 void main() { |
| 354 [[highlight]]querySelector('#inputName').onInput.listen(updateBadge);[[/highli
ght]] |
| 355 } |
| 356 {% endprettify %} |
| 357 </div> |
| 358 |
| 359 <div class="trydart-filename">piratebadge.dart</div> |
| 360 |
| 361 </div> <div class="span5" markdown="1"> |
| 362 |
| 363 * The `querySelector()` function, defined in |
| 364 dart:html, gets an element from the DOM. |
| 365 Here, the code uses the ID `#inputName` |
| 366 to specify the input field. |
| 367 |
| 368 * `onInput` registers an event handler for input events. |
| 369 |
| 370 * An input event occurs when the user presses a key. |
| 371 |
| 372 * You can use either single or double quotes to create a string. |
| 373 |
| 374 * Dart Editor warns you that the function doesn't exist. |
| 375 Let's fix that now. |
| 376 |
| 377 </div> </div> |
| 378 |
| 379 <div class="trydart-step-details" markdown="1"> |
| 380 |
| 381 <hr> |
| 382 |
| 383 Implement the event handler as a top-level function. |
| 384 </div> |
| 385 |
| 386 <div class="row"> <div class="span7"> |
| 387 |
| 388 <div class="trydart-step-details" markdown="1"> |
| 389 |
| 390 {% prettify dart %} |
| 391 ... |
| 392 |
| 393 [[highlight]]void updateBadge(Event e) { |
| 394 querySelector('#badgeName').text = (e.target as InputElement).value; |
| 395 }[[/highlight]] |
| 396 {% endprettify %} |
| 397 </div> |
| 398 |
| 399 <div class="trydart-filename">piratebadge.dart</div> |
| 400 |
| 401 </div> <div class="span5" markdown="1"> |
| 402 |
| 403 * This function sets the text of the `badgeName` element from the value of the i
nput field. |
| 404 |
| 405 * You can tell that `updateBadge()` is an event handler because it takes an |
| 406 `Event` object. |
| 407 |
| 408 * The element that generated the event, the input field, is `e.target`. |
| 409 |
| 410 * The `as` keyword typecasts `e.target` to an |
| 411 `InputElement`. |
| 412 |
| 413 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 414 |
| 415 </div> </div> |
| 416 |
| 417 #### <i class="icon-anchor"> </i> Run the app. |
| 418 |
| 419 <div class="trydart-step-details" markdown="1"> |
| 420 |
| 421 Save your files with **File > Save All**. |
| 422 |
| 423 Use the Run button |
| 424 <img src="images/run.png" width="16" height="16" |
| 425 alt="Run button"> |
| 426 in Dart Editor to run the app. |
| 427 |
| 428 Compare your app to the one running below. |
| 429 |
| 430 Type in the input field. |
| 431 |
| 432 <iframe class="running-app-frame" |
| 433 style="height:220px;width:530px;" |
| 434 src="examples/2-inputnamebadge/piratebadge.html"> |
| 435 </iframe> |
| 436 |
| 437 ##### Problems? |
| 438 |
| 439 Check your code against the files in `2-inputbadge`. |
| 440 |
| 441 * [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/2-inputnamebadge/piratebadge.html) |
| 442 |
| 443 * [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/2-inputnamebadge/piratebadge.dart) |
| 444 </div> |
| 445 |
| 446 |
| 447 <hr> |
| 448 |
| 449 ##Step 3: Add a button {#step-three} |
| 450 |
| 451 In this step, you add a button to the app. |
| 452 The button is enabled when the text field contains no text. |
| 453 When the user clicks the button, |
| 454 the app puts the name `Anne Bonney` on the badge. |
| 455 |
| 456 #### <i class="icon-anchor"> </i> Edit piratebadge.html. |
| 457 |
| 458 <div class="trydart-step-details" markdown="1"> |
| 459 Add the <button> tag below the input field. |
| 460 </div> |
| 461 |
| 462 <div class="row"> <div class="span7"> |
| 463 |
| 464 <div class="trydart-step-details"> |
| 465 {% prettify html %} |
| 466 ... |
| 467 <div class="widgets"> |
| 468 <div> |
| 469 <input type="text" id="inputName" maxlength="15"> |
| 470 </div> |
| 471 [[highlight]] <div> |
| 472 <button id="generateButton">Aye! Gimme a name!</button> |
| 473 </div>[[/highlight]] |
| 474 </div> |
| 475 ... |
| 476 {% endprettify %} |
| 477 </div> |
| 478 |
| 479 <div class="trydart-filename">piratebadge.html</div> |
| 480 |
| 481 </div> <div class="span5" markdown="1"> |
| 482 |
| 483 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 484 |
| 485 * The button has the ID `generateButton` so |
| 486 the Dart code can get the element. |
| 487 |
| 488 </div> </div> |
| 489 |
| 490 #### <i class="icon-anchor"> </i> Edit piragebadge.dart. |
| 491 |
| 492 <div class="trydart-step-details" markdown="1"> |
| 493 Below the import, declare a top-level variable to hold the `ButtonElement`. |
| 494 </div> |
| 495 |
| 496 <div class="row"> <div class="span7"> |
| 497 |
| 498 <div class="trydart-step-details"> |
| 499 {% prettify dart %} |
| 500 import 'dart:html'; |
| 501 |
| 502 [[highlight]]ButtonElement genButton;[[/highlight]] |
| 503 {% endprettify %} |
| 504 </div> |
| 505 |
| 506 <div class="trydart-filename">piratebadge.dart</div> |
| 507 |
| 508 </div> <div class="span5" markdown="1"> |
| 509 |
| 510 * Top-level variables are names at the library level. |
| 511 |
| 512 * ButtonElement is one of many different kinds of DOM elements |
| 513 provided by the dart:html library. |
| 514 |
| 515 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 516 |
| 517 </div> </div> |
| 518 |
| 519 <div class="trydart-step-details" markdown="1"> |
| 520 |
| 521 <hr> |
| 522 |
| 523 Wire up the button with an event handler. |
| 524 </div> |
| 525 |
| 526 <div class="row"> <div class="span7"> |
| 527 |
| 528 <div class="trydart-step-details"> |
| 529 {% prettify dart %} |
| 530 void main() { |
| 531 querySelector('#inputName').onInput.listen(updateBadge); |
| 532 [[highlight]]genButton = querySelector('#generateButton'); |
| 533 genButton.onClick.listen(generateBadge);[[/highlight]] |
| 534 } |
| 535 {% endprettify %} |
| 536 </div> |
| 537 |
| 538 <div class="trydart-filename">piratebadge.dart</div> |
| 539 |
| 540 </div> <div class="span5" markdown="1"> |
| 541 |
| 542 * `onClick` registers a mouse click handler. |
| 543 |
| 544 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 545 |
| 546 </div> </div> |
| 547 |
| 548 <div class="trydart-step-details" markdown="1"> |
| 549 |
| 550 <hr> |
| 551 |
| 552 Add a top-level function that changes the name on the badge. |
| 553 </div> |
| 554 |
| 555 <div class="row"> <div class="span7"> |
| 556 |
| 557 <div class="trydart-step-details"> |
| 558 {% prettify dart %} |
| 559 ... |
| 560 |
| 561 [[highlight]]void setBadgeName(String newName) { |
| 562 querySelector('#badgeName').text = newName; |
| 563 } [[/highlight]] |
| 564 {% endprettify %} |
| 565 </div> |
| 566 |
| 567 <div class="trydart-filename">piratebadge.dart</div> |
| 568 |
| 569 </div> <div class="span5" markdown="1"> |
| 570 |
| 571 * The function updates the HTML page with a new name. |
| 572 |
| 573 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 574 |
| 575 </div> </div> |
| 576 |
| 577 <div class="trydart-step-details" markdown="1"> |
| 578 |
| 579 <hr> |
| 580 |
| 581 Implement the click handler for the button. |
| 582 </div> |
| 583 |
| 584 <div class="row"> <div class="span7"> |
| 585 |
| 586 <div class="trydart-step-details"> |
| 587 {% prettify dart %} |
| 588 ... |
| 589 |
| 590 [[highlight]]void generateBadge(Event e) { |
| 591 setBadgeName('Anne Bonney'); |
| 592 }[[/highlight]] |
| 593 {% endprettify %} |
| 594 </div> |
| 595 |
| 596 <div class="trydart-filename">piratebadge.dart</div> |
| 597 |
| 598 </div> <div class="span5" markdown="1"> |
| 599 |
| 600 * This function sets the badge name to `Anne Bonney`. |
| 601 |
| 602 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 603 |
| 604 </div> </div> |
| 605 |
| 606 <div class="trydart-step-details" markdown="1"> |
| 607 |
| 608 <hr> |
| 609 Modify `updateBadge()` to call `setBadgeName()`. |
| 610 </div> |
| 611 |
| 612 <div class="row"> <div class="span7"> |
| 613 |
| 614 <div class="trydart-step-details"> |
| 615 {% prettify dart %} |
| 616 void updateBadge(Event e) { |
| 617 [[highlight]] String inputName = [[/highlight]](e.target as InputElement).value
; |
| 618 [[highlight]] setBadgeName(inputName);[[/highlight]] |
| 619 } |
| 620 {% endprettify %} |
| 621 </div> |
| 622 |
| 623 <div class="trydart-filename">piratebadge.dart</div> |
| 624 |
| 625 </div> <div class="span5" markdown="1"> |
| 626 |
| 627 * Assign the input field's value to a local string. |
| 628 |
| 629 </div></div> |
| 630 |
| 631 |
| 632 <div class="trydart-step-details" markdown="1"> |
| 633 |
| 634 <hr> |
| 635 |
| 636 Now add code to `updateBadge()` to enable and disable the button as needed. |
| 637 </div> |
| 638 |
| 639 <div class="row"> <div class="span7"> |
| 640 |
| 641 <div class="trydart-step-details"> |
| 642 {% prettify dart %} |
| 643 void updateBadge(Event e) { |
| 644 String inputName = (e.target as InputElement).value; |
| 645 setBadgeName(inputName); |
| 646 [[highlight]] if (inputName.trim().isEmpty) { |
| 647 genButton..disabled = false |
| 648 ..text = 'Aye! Gimme a name!'; |
| 649 } else { |
| 650 genButton..disabled = true |
| 651 ..text = 'Arrr! Write yer name!'; |
| 652 }[[/highlight]] |
| 653 } |
| 654 {% endprettify %} |
| 655 </div> |
| 656 |
| 657 <div class="trydart-filename">piratebadge.dart</div> |
| 658 |
| 659 </div> <div class="span5" markdown="1"> |
| 660 |
| 661 * The `String` class has useful functions and properties for dealing with string
s, |
| 662 such as `trim()` and `isEmpty`. |
| 663 |
| 664 * String comes from the `dart:core` library, |
| 665 which is automatically imported into every Dart program. |
| 666 |
| 667 * The cascade operator (`..`) allows you to perform multiple |
| 668 operations on the members of a single object. |
| 669 |
| 670 * Dart has common programming language constructs like `if`-`else`. |
| 671 |
| 672 </div></div> |
| 673 |
| 674 #### <i class="icon-anchor"> </i> Run the app. |
| 675 |
| 676 <div class="trydart-step-details" markdown="1"> |
| 677 |
| 678 Save your files with **File > Save All**. |
| 679 |
| 680 Use the Run button |
| 681 <img src="images/run.png" width="16" height="16" |
| 682 alt="Run button"> |
| 683 in Dart Editor to run the app. |
| 684 |
| 685 Compare your app to the one running below. |
| 686 |
| 687 Type in the input field. |
| 688 Remove the text from the input field. |
| 689 Click the button. |
| 690 |
| 691 <iframe class="running-app-frame" |
| 692 style="height:220px;width:530px;" |
| 693 src="examples/3-buttonbadge/piratebadge.html"> |
| 694 </iframe> |
| 695 |
| 696 |
| 697 ##### Problems? |
| 698 |
| 699 Check your code against the files in `3-buttonbadge`. |
| 700 |
| 701 * [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/3-buttonbadge/piratebadge.html) |
| 702 |
| 703 * [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/3-buttonbadge/piratebadge.dart) |
| 704 |
| 705 </div> |
| 706 |
| 707 |
| 708 <hr> |
| 709 |
| 710 ##Step 4: Create a PirateName class {#step-four} |
| 711 |
| 712 In this step, you change only the Dart code. |
| 713 You create a class to represent a pirate name. |
| 714 When created, an instance of this class |
| 715 randomly selects a name and appellation from a list, |
| 716 or optionally you can provide a name |
| 717 and an appellation to the constructor. |
| 718 |
| 719 #### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
| 720 |
| 721 <div class="trydart-step-details" markdown="1"> |
| 722 Add an import to the top of the file. |
| 723 </div> |
| 724 |
| 725 <div class="row"> <div class="span7"> |
| 726 |
| 727 <div class="trydart-step-details"> |
| 728 {% prettify dart %} |
| 729 import 'dart:html'; |
| 730 |
| 731 [[highlight]]import 'dart:math' show Random;[[/highlight]] |
| 732 {% endprettify %} |
| 733 </div> |
| 734 |
| 735 <div class="trydart-filename">piratebadge.dart</div> |
| 736 |
| 737 </div> <div class="span5" markdown="1"> |
| 738 |
| 739 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 740 |
| 741 * Using the `show` keyword, |
| 742 you can import only the classes, functions, or properties you need. |
| 743 |
| 744 * `Random` provides a random number generator. |
| 745 |
| 746 </div></div> |
| 747 |
| 748 <div class="trydart-step-details" markdown="1"> |
| 749 |
| 750 <hr> |
| 751 |
| 752 Add a class declaration to the bottom of the file. |
| 753 </div> |
| 754 |
| 755 <div class="row"> <div class="span7"> |
| 756 |
| 757 <div class="trydart-step-details"> |
| 758 {% prettify dart %} |
| 759 ... |
| 760 |
| 761 [[highlight]]class PirateName { |
| 762 }[[/highlight]] |
| 763 {% endprettify %} |
| 764 </div> |
| 765 |
| 766 <div class="trydart-filename">piratebadge.dart</div> |
| 767 |
| 768 </div> <div class="span5" markdown="1"> |
| 769 |
| 770 * The class declaration provides the class name. |
| 771 |
| 772 </div></div> |
| 773 |
| 774 <div class="trydart-step-details" markdown="1"> |
| 775 |
| 776 <hr> |
| 777 |
| 778 Create a class-level Random object. |
| 779 </div> |
| 780 |
| 781 <div class="row"> <div class="span7"> |
| 782 |
| 783 <div class="trydart-step-details"> |
| 784 {% prettify dart %} |
| 785 class PirateName { |
| 786 [[highlight]]static final Random indexGen = new Random();[[/highlight]] |
| 787 } |
| 788 {% endprettify %} |
| 789 </div> |
| 790 |
| 791 <div class="trydart-filename">piratebadge.dart</div> |
| 792 |
| 793 </div> <div class="span5" markdown="1"> |
| 794 |
| 795 * `static` defines a class-level field. That is, |
| 796 the random number generator is shared with all |
| 797 instances of this class. |
| 798 |
| 799 * Dart Editor italicizes static names. |
| 800 |
| 801 * Use `new` to call a constructor. |
| 802 |
| 803 </div></div> |
| 804 |
| 805 <div class="trydart-step-details" markdown="1"> |
| 806 |
| 807 <hr> |
| 808 |
| 809 Add two instance variables to class, |
| 810 one for the first name and one for the appellation. |
| 811 </div> |
| 812 |
| 813 <div class="row"> <div class="span7"> |
| 814 |
| 815 <div class="trydart-step-details"> |
| 816 {% prettify dart %} |
| 817 class PirateName { |
| 818 static final Random indexGen = new Random(); |
| 819 [[highlight]] String _firstName; |
| 820 String _appellation;[[/highlight]] |
| 821 } |
| 822 {% endprettify %} |
| 823 </div> |
| 824 |
| 825 <div class="trydart-filename">piratebadge.dart</div> |
| 826 |
| 827 </div> <div class="span5" markdown="1"> |
| 828 |
| 829 * Private variables start with underscore (`_`). |
| 830 |
| 831 </div></div> |
| 832 |
| 833 <div class="trydart-step-details" markdown="1"> |
| 834 |
| 835 <hr> |
| 836 |
| 837 Create two static lists within the class |
| 838 that provide a small collection of names and appellations to choose from. |
| 839 </div> |
| 840 |
| 841 <div class="row"> <div class="span7"> |
| 842 |
| 843 <div class="trydart-step-details"> |
| 844 {% prettify dart %} |
| 845 class PirateName { |
| 846 ... |
| 847 [[highlight]] static final List names = [ |
| 848 'Anne', 'Mary', 'Jack', 'Morgan', 'Roger', |
| 849 'Bill', 'Ragnar', 'Ed', 'John', 'Jane' ]; |
| 850 static final List appellations = [ |
| 851 'Black','Damned', 'Jackal', 'Red', 'Stalwart', 'Axe', |
| 852 'Young', 'Old', 'Angry', 'Brave', 'Crazy', 'Noble'];[[/highlight]] |
| 853 } |
| 854 {% endprettify %} |
| 855 </div> |
| 856 |
| 857 <div class="trydart-filename">piratebadge.dart</div> |
| 858 |
| 859 </div> <div class="span5" markdown="1"> |
| 860 |
| 861 * `final` variables cannot change. |
| 862 |
| 863 * Lists are built into the language. |
| 864 These lists are created using list literals. |
| 865 |
| 866 * The `List` class provides the API for lists. |
| 867 |
| 868 </div></div> |
| 869 |
| 870 |
| 871 <div class="trydart-step-details" markdown="1"> |
| 872 |
| 873 <hr> |
| 874 |
| 875 Provide a constructor for the class. |
| 876 </div> |
| 877 |
| 878 <div class="row"> <div class="span7"> |
| 879 |
| 880 <div class="trydart-step-details"> |
| 881 {% prettify dart %} |
| 882 class PirateName { |
| 883 ... |
| 884 [[highlight]] PirateName({String firstName, String appellation}) { |
| 885 if (firstName == null) { |
| 886 _firstName = names[indexGen.nextInt(names.length)]; |
| 887 } else { |
| 888 _firstName = firstName; |
| 889 } |
| 890 if (appellation == null) { |
| 891 _appellation = appellations[indexGen.nextInt(appellations.length)]; |
| 892 } else { |
| 893 _appellation = appellation; |
| 894 } |
| 895 }[[/highlight]] |
| 896 } |
| 897 {% endprettify %} |
| 898 </div> |
| 899 |
| 900 <div class="trydart-filename">piratebadge.dart</div> |
| 901 |
| 902 </div> <div class="span5" markdown="1"> |
| 903 |
| 904 * Constructors have the same name as the class. |
| 905 |
| 906 * The parameters enclosed in curly brackets (`{` and `}`) |
| 907 are optional, named parameters. |
| 908 |
| 909 * The `nextInt()` function gets a new random integer |
| 910 from the random number generator. |
| 911 |
| 912 * Use square brackets (`[` and `]`) to index into a list. |
| 913 |
| 914 * The `length` property returns the number of items in a list. |
| 915 |
| 916 * The code uses a random number as an index into the list. |
| 917 |
| 918 </div> </div> |
| 919 |
| 920 <div class="trydart-step-details" markdown="1"> |
| 921 |
| 922 <hr> |
| 923 |
| 924 Provide a getter for the pirate name. |
| 925 </div> |
| 926 |
| 927 <div class="row"> <div class="span7"> |
| 928 |
| 929 <div class="trydart-step-details"> |
| 930 {% prettify dart %} |
| 931 class PirateName { |
| 932 ... |
| 933 [[highlight]] String get pirateName => |
| 934 _firstName.isEmpty ? '' : '$_firstName the $_appellation';[[/highlight]] |
| 935 } |
| 936 {% endprettify %} |
| 937 </div> |
| 938 |
| 939 <div class="trydart-filename">piratebadge.dart</div> |
| 940 |
| 941 </div><div class="span5" markdown="1"> |
| 942 |
| 943 * Getters are special methods that provide read access to an object’s properties
. |
| 944 |
| 945 * The ternary operator `?:` is short-hand for an if-then-else statement. |
| 946 |
| 947 * String interpolation |
| 948 (`'$_firstName the $_appellation'`) |
| 949 lets you easily build strings from other objects. |
| 950 |
| 951 * The fat arrow (` => expr; `) syntax is a shorthand for `{ return expr; }`. |
| 952 |
| 953 </div></div> |
| 954 |
| 955 <div class="trydart-step-details" markdown="1"> |
| 956 |
| 957 <hr> |
| 958 |
| 959 Modify the function `setBadgeName()` to use a PirateName instead of a String: |
| 960 </div> |
| 961 |
| 962 <div class="row"> <div class="span7"> |
| 963 |
| 964 <div class="trydart-step-details"> |
| 965 {% prettify dart %} |
| 966 void setBadgeName([[highlight]]PirateName[[/highlight]] newName) { |
| 967 querySelector('#badgeName').text = newName[[highlight]].pirateName[[/highlight
]]; |
| 968 } |
| 969 {% endprettify %} |
| 970 </div> |
| 971 |
| 972 <div class="trydart-filename">piratebadge.dart</div> |
| 973 |
| 974 </div><div class="span5" markdown="1"> |
| 975 |
| 976 * This code calls the getter to get the PirateName as a string. |
| 977 |
| 978 </div></div> |
| 979 |
| 980 <div class="trydart-step-details" markdown="1"> |
| 981 |
| 982 <hr> |
| 983 |
| 984 Change `updateBadge()` to generate a PirateName based on the input field value. |
| 985 </div> |
| 986 |
| 987 <div class="row"> <div class="span7"> |
| 988 |
| 989 <div class="trydart-step-details"> |
| 990 {% prettify dart %} |
| 991 void updateBadge(Event e) { |
| 992 String inputName = (e.target as InputElement).value; |
| 993 |
| 994 [[highlight]]setBadgeName(new PirateName(firstName: inputName));[[/highlight]] |
| 995 ... |
| 996 } |
| 997 {% endprettify %} |
| 998 </div> |
| 999 |
| 1000 <div class="trydart-filename">piratebadge.dart</div> |
| 1001 |
| 1002 </div><div class="span5" markdown="1"> |
| 1003 |
| 1004 * The call to the constructor provides a value for one optional named parameter. |
| 1005 |
| 1006 </div></div> |
| 1007 |
| 1008 <div class="trydart-step-details" markdown="1"> |
| 1009 |
| 1010 <hr> |
| 1011 |
| 1012 Change `generateBadge()` to generate a PirateName instead of using `Anne Bonney`
. |
| 1013 </div> |
| 1014 |
| 1015 <div class="row"> <div class="span7"> |
| 1016 |
| 1017 <div class="trydart-step-details"> |
| 1018 {% prettify dart %} |
| 1019 void generateBadge(Event e) { |
| 1020 setBadgeName([[highlight]]new PirateName()[[/highlight]]); |
| 1021 } |
| 1022 {% endprettify %} |
| 1023 </div> |
| 1024 |
| 1025 <div class="trydart-filename">piratebadge.dart</div> |
| 1026 |
| 1027 </div><div class="span5" markdown="1"> |
| 1028 |
| 1029 * In this case, the call to the constructor passes no parameters. |
| 1030 |
| 1031 </div></div> |
| 1032 |
| 1033 #### <i class="icon-anchor"> </i> Run the app. |
| 1034 |
| 1035 <div class="trydart-step-details" markdown="1"> |
| 1036 |
| 1037 Save your files with **File > Save All**. |
| 1038 |
| 1039 Use the Run button |
| 1040 <img src="images/run.png" width="16" height="16" |
| 1041 alt="Run button"> |
| 1042 in Dart Editor to run the app. |
| 1043 |
| 1044 Compare your app to the one running below. |
| 1045 |
| 1046 Type in the input field. |
| 1047 Remove the text from the input field. |
| 1048 Click the button. |
| 1049 |
| 1050 <iframe class="running-app-frame" |
| 1051 style="height:220px;width:530px;" |
| 1052 src="examples/4-classbadge/piratebadge.html"> |
| 1053 </iframe> |
| 1054 |
| 1055 |
| 1056 ##### Problems? |
| 1057 |
| 1058 Check your code against the files in `4-classbadge`. |
| 1059 |
| 1060 * [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/4-classbadge/piratebadge.html) |
| 1061 |
| 1062 * [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/4-classbadge/piratebadge.dart) |
| 1063 |
| 1064 </div> |
| 1065 |
| 1066 |
| 1067 <hr> |
| 1068 |
| 1069 |
| 1070 ##Step 5: Save to local storage {#step-five} |
| 1071 |
| 1072 In this step, you give the app some persistence |
| 1073 by saving the badge name to local storage each time it changes. |
| 1074 When you restart the app, |
| 1075 it initializes the badge from the saved name. |
| 1076 |
| 1077 #### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
| 1078 |
| 1079 <div class="trydart-step-details" markdown="1"> |
| 1080 Import the JSON converter from the `dart:convert` library. |
| 1081 </div> |
| 1082 |
| 1083 <div class="row"> <div class="span7"> |
| 1084 |
| 1085 <div class="trydart-step-details"> |
| 1086 {% prettify dart %} |
| 1087 import 'dart:html'; |
| 1088 import 'dart:math' show Random; |
| 1089 [[highlight]] |
| 1090 import 'dart:convert' show JSON;[[/highlight]] |
| 1091 {% endprettify %} |
| 1092 </div> |
| 1093 |
| 1094 <div class="trydart-filename">piratebadge.dart</div> |
| 1095 |
| 1096 </div> <div class="span5" markdown="1"> |
| 1097 |
| 1098 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 1099 |
| 1100 * `JSON` provides convenient access to the most common JSON use cases. |
| 1101 |
| 1102 </div> </div> |
| 1103 |
| 1104 <div class="trydart-step-details" markdown="1"> |
| 1105 |
| 1106 <hr> |
| 1107 |
| 1108 Add a named constructor to the PirateName class. |
| 1109 </div> |
| 1110 |
| 1111 <div class="row"> <div class="span7"> |
| 1112 |
| 1113 <div class="trydart-step-details"> |
| 1114 {% prettify dart %} |
| 1115 class PirateName { |
| 1116 ... |
| 1117 [[highlight]] PirateName.fromJSON(String jsonString) { |
| 1118 Map storedName = JSON.decode(jsonString); |
| 1119 _firstName = storedName['f']; |
| 1120 _appellation = storedName['a']; |
| 1121 }[[/highlight]] |
| 1122 } |
| 1123 {% endprettify %} |
| 1124 </div> |
| 1125 |
| 1126 <div class="trydart-filename">piratebadge.dart</div> |
| 1127 |
| 1128 </div> <div class="span5" markdown="1"> |
| 1129 |
| 1130 * The constructor creates a new PirateName instance from a JSON-encoded string. |
| 1131 |
| 1132 * `PirateName.fromJson` is a named constructor. |
| 1133 |
| 1134 * `JSON.decode()` parses a JSON string and creates Dart objects from it. |
| 1135 |
| 1136 * The pirate name is decoded into a `Map` object. |
| 1137 |
| 1138 </div> </div> |
| 1139 |
| 1140 <div class="trydart-step-details" markdown="1"> |
| 1141 |
| 1142 <hr> |
| 1143 |
| 1144 Add a getter to the PirateName class |
| 1145 that encodes a pirate name in a JSON string. |
| 1146 </div> |
| 1147 |
| 1148 <div class="row"> <div class="span7"> |
| 1149 |
| 1150 <div class="trydart-step-details"> |
| 1151 {% prettify dart %} |
| 1152 class PirateName { |
| 1153 ... |
| 1154 [[highlight]]String get jsonString => '{ "f": "$_firstName", "a": "$_appellati
on" } ';[[/highlight]] |
| 1155 } |
| 1156 {% endprettify %} |
| 1157 </div> |
| 1158 |
| 1159 <div class="trydart-filename">piratebadge.dart</div> |
| 1160 |
| 1161 </div> <div class="span5" markdown="1"> |
| 1162 |
| 1163 * The getter formats the JSON string using the map format. |
| 1164 |
| 1165 </div> </div> |
| 1166 |
| 1167 |
| 1168 <div class="trydart-step-details" markdown="1"> |
| 1169 |
| 1170 <hr> |
| 1171 |
| 1172 Declare a top-level string. |
| 1173 </div> |
| 1174 |
| 1175 <div class="row"> <div class="span7"> |
| 1176 |
| 1177 <div class="trydart-step-details"> |
| 1178 {% prettify dart %} |
| 1179 [[highlight]]final String TREASURE_KEY = 'pirateName';[[/highlight]] |
| 1180 |
| 1181 void main() { |
| 1182 ... |
| 1183 } |
| 1184 {% endprettify %} |
| 1185 </div> |
| 1186 |
| 1187 <div class="trydart-filename">piratebadge.dart</div> |
| 1188 |
| 1189 </div> <div class="span5" markdown="1"> |
| 1190 |
| 1191 * This string is a key to the local storage. |
| 1192 |
| 1193 </div> </div> |
| 1194 |
| 1195 <div class="trydart-step-details" markdown="1"> |
| 1196 |
| 1197 <hr> |
| 1198 |
| 1199 Save the pirate name when the badge name changes. |
| 1200 </div> |
| 1201 |
| 1202 <div class="row"> <div class="span7"> |
| 1203 |
| 1204 <div class="trydart-step-details"> |
| 1205 {% prettify dart %} |
| 1206 void setBadgeName(PirateName newName) { |
| 1207 [[highlight]]if (newName == null) { |
| 1208 return; |
| 1209 }[[/highlight]] |
| 1210 querySelector('#badgeName').text = newName.pirateName; |
| 1211 [[highlight]]window.localStorage[TREASURE_KEY] = newName.jsonString;[[/highlig
ht]] |
| 1212 } |
| 1213 {% endprettify %} |
| 1214 </div> |
| 1215 |
| 1216 <div class="trydart-filename">piratebadge.dart</div> |
| 1217 |
| 1218 </div> <div class="span5" markdown="1"> |
| 1219 |
| 1220 * Local storage is provided by the browser's `Window`. |
| 1221 |
| 1222 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 1223 |
| 1224 </div> </div> |
| 1225 |
| 1226 <div class="trydart-step-details" markdown="1"> |
| 1227 |
| 1228 <hr> |
| 1229 |
| 1230 Add a top-level function called `getBadgeNameFromStorage()`. |
| 1231 </div> |
| 1232 |
| 1233 <div class="row"> <div class="span7"> |
| 1234 |
| 1235 <div class="trydart-step-details"> |
| 1236 {% prettify dart %} |
| 1237 void setBadgeName(PirateName newName) { |
| 1238 ... |
| 1239 } |
| 1240 |
| 1241 [[highlight]]PirateName getBadgeNameFromStorage() { |
| 1242 String storedName = window.localStorage[TREASURE_KEY]; |
| 1243 if (storedName != null) { |
| 1244 return new PirateName.fromJSON(storedName); |
| 1245 } else { |
| 1246 return null; |
| 1247 } |
| 1248 }[[/highlight]] |
| 1249 {% endprettify %} |
| 1250 </div> |
| 1251 |
| 1252 <div class="trydart-filename">piratebadge.dart</div> |
| 1253 |
| 1254 </div> <div class="span5" markdown="1"> |
| 1255 |
| 1256 * The function retrieves the pirate name from local storage |
| 1257 and creates a PirateName object from it. |
| 1258 |
| 1259 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 1260 |
| 1261 </div> </div> |
| 1262 |
| 1263 <div class="trydart-step-details" markdown="1"> |
| 1264 <hr> |
| 1265 Call the function from the `main()` function. |
| 1266 </div> |
| 1267 |
| 1268 <div class="row"> <div class="span7"> |
| 1269 |
| 1270 <div class="trydart-step-details"> |
| 1271 {% prettify dart %} |
| 1272 void main() { |
| 1273 ... |
| 1274 [[highlight]]setBadgeName(getBadgeNameFromStorage());[[/highlight]] |
| 1275 } |
| 1276 {% endprettify %} |
| 1277 </div> |
| 1278 |
| 1279 <div class="trydart-filename">piratebadge.dart</div> |
| 1280 |
| 1281 </div> <div class="span5" markdown="1"> |
| 1282 |
| 1283 * Initialize the badge name from local storage. |
| 1284 |
| 1285 {% comment %} non-breaking space required for bootstrap/markdown bogosity
{% endcomment %} |
| 1286 |
| 1287 </div> </div> |
| 1288 |
| 1289 #### <i class="icon-anchor"> </i> Run the app. |
| 1290 |
| 1291 <div class="trydart-step-details" markdown="1"> |
| 1292 |
| 1293 Save your files with **File > Save All**. |
| 1294 |
| 1295 Use the Run button |
| 1296 <img src="images/run.png" width="16" height="16" |
| 1297 alt="Run button"> |
| 1298 in Dart Editor to run the app. |
| 1299 |
| 1300 Compare your app to the one running below. |
| 1301 |
| 1302 Click the button to put a name on the badge. |
| 1303 Start the app again by duplicating this window. |
| 1304 |
| 1305 <iframe class="running-app-frame" |
| 1306 style="height:220px;width:530px;" |
| 1307 src="examples/5-localbadge/piratebadge.html"> |
| 1308 </iframe> |
| 1309 |
| 1310 |
| 1311 ##### Problems? |
| 1312 |
| 1313 Check your code against the files in `5-localbadge`. |
| 1314 |
| 1315 * [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/5-localbadge/piratebadge.html) |
| 1316 |
| 1317 * [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/5-localbadge/piratebadge.dart) |
| 1318 |
| 1319 </div> |
| 1320 |
| 1321 |
| 1322 <hr> |
| 1323 |
| 1324 |
| 1325 ##Step 6: Read names from JSON-encoded file {#step-six} |
| 1326 |
| 1327 In this step, you change the PirateName class to get |
| 1328 the list of names and appellations from a JSON file. |
| 1329 This gives you a chance to add more names and |
| 1330 appellations to the program. |
| 1331 |
| 1332 #### <i class="icon-anchor"> </i> Create piratenames.json. |
| 1333 |
| 1334 <div class="trydart-step-details" markdown="1"> |
| 1335 Use **File > New File...** to create a JSON-encoded file |
| 1336 named `piratenames.json` with the following content. |
| 1337 |
| 1338 Put the file in `1-blankbadge` alongside the Dart and HTML files you've been edi
ting. |
| 1339 </div> |
| 1340 |
| 1341 <div class="row"> <div class="span7"> |
| 1342 |
| 1343 <div class="trydart-step-details"> |
| 1344 {% prettify dart %} |
| 1345 { "names": [ "Anne", "Bette", "Cate", "Dawn", |
| 1346 "Elise", "Faye", "Ginger", "Harriot", |
| 1347 "Izzy", "Jane", "Kaye", "Liz", |
| 1348 "Maria", "Nell", "Olive", "Pat", |
| 1349 "Queenie", "Rae", "Sal", "Tam", |
| 1350 "Uma", "Violet", "Wilma", "Xana", |
| 1351 "Yvonne", "Zelda", |
| 1352 "Abe", "Billy", "Caleb", "Davie", |
| 1353 "Eb", "Frank", "Gabe", "House", |
| 1354 "Icarus", "Jack", "Kurt", "Larry", |
| 1355 "Mike", "Nolan", "Oliver", "Pat", |
| 1356 "Quib", "Roy", "Sal", "Tom", |
| 1357 "Ube", "Val", "Walt", "Xavier", |
| 1358 "Yvan", "Zeb"], |
| 1359 "appellations": [ "Awesome", "Black", "Captain", "Damned", |
| 1360 "Even", "Fighter", "Great", "Hearty", |
| 1361 "Irate", "Jackal", "King", "Lord", |
| 1362 "Mighty", "Noble", "Old", "Powerful", |
| 1363 "Quick", "Red", "Stalwart", "Tank", |
| 1364 "Ultimate", "Vicious", "Wily", "aXe", |
| 1365 "Young", "Zealot", |
| 1366 "Angry", "Brave", "Crazy", "Damned", |
| 1367 "Eager", "Fool", "Greedy", "Hated", |
| 1368 "Idiot", "Jinxed", "Kind", "Lame", |
| 1369 "Maimed", "Naked", "Old", "Pale", |
| 1370 "Queasy", "Rat", "Sandy", "Tired", |
| 1371 "Ugly", "Vile", "Weak", "Xeric", |
| 1372 "Yellow", "Zesty"]} |
| 1373 {% endprettify %} |
| 1374 </div> |
| 1375 |
| 1376 <div class="trydart-filename">piratenames.json</div> |
| 1377 |
| 1378 </div> <div class="span5" markdown="1"> |
| 1379 |
| 1380 <i class="icon-key"> </i> <strong> Key Information </strong> |
| 1381 |
| 1382 * The file contains a JSON-encoded map, |
| 1383 which contains two lists of strings. |
| 1384 |
| 1385 </div> </div> |
| 1386 |
| 1387 #### <i class="icon-anchor"> </i> Edit piratebadge.html. |
| 1388 |
| 1389 <div class="trydart-step-details" markdown="1"> |
| 1390 Disable the input field and the button. |
| 1391 </div> |
| 1392 |
| 1393 <div class="row"> <div class="span7"> |
| 1394 |
| 1395 <div class="trydart-step-details"> |
| 1396 {% prettify html %} |
| 1397 ... |
| 1398 <div> |
| 1399 <input type="text" id="inputName" maxlength="15" [[highlight]]disabled[[/hig
hlight]]> |
| 1400 </div> |
| 1401 <div> |
| 1402 <button id="generateButton" [[highlight]]disabled[[/highlight]]>Aye! Gimme a
name!</button> |
| 1403 </div> |
| 1404 ... |
| 1405 {% endprettify %} |
| 1406 </div> |
| 1407 |
| 1408 <div class="trydart-filename">piratebadge.html</div> |
| 1409 |
| 1410 </div> <div class="span5" markdown="1"> |
| 1411 |
| 1412 |
| 1413 * The Dart code enables the text field and |
| 1414 the button after the pirate names are successfully read from |
| 1415 the JSON file. |
| 1416 |
| 1417 </div> </div> |
| 1418 |
| 1419 #### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
| 1420 |
| 1421 <div class="trydart-step-details" markdown="1"> |
| 1422 |
| 1423 Add an import to the top of the file. |
| 1424 </div> |
| 1425 |
| 1426 <div class="row"> <div class="span7"> |
| 1427 |
| 1428 <div class="trydart-step-details"> |
| 1429 {% prettify dart %} |
| 1430 import 'dart:html'; |
| 1431 import 'dart:math' show Random; |
| 1432 import 'dart:convert' show JSON; |
| 1433 |
| 1434 [[highlight]]import 'dart:async' show Future;[[/highlight]] |
| 1435 {% endprettify %} |
| 1436 </div> |
| 1437 |
| 1438 <div class="trydart-filename">piratebadge.dart</div> |
| 1439 |
| 1440 </div> <div class="span5" markdown="1"> |
| 1441 |
| 1442 * The `dart:async` library provides for asynchronous programming. |
| 1443 |
| 1444 * A `Future` provides a way to get a value in the future. |
| 1445 |
| 1446 </div> </div> |
| 1447 |
| 1448 <div class="trydart-step-details" markdown="1"> |
| 1449 |
| 1450 <hr> |
| 1451 Replace the `names` and `appellations` lists with these static, empty lists: |
| 1452 </div> |
| 1453 |
| 1454 <div class="row"> <div class="span7"> |
| 1455 |
| 1456 <div class="trydart-step-details"> |
| 1457 {% prettify dart %} |
| 1458 class PirateName { |
| 1459 ... |
| 1460 [[highlight]]static List<String> names = []; |
| 1461 static List<String> appellations = [];[[/highlight]] |
| 1462 ... |
| 1463 } |
| 1464 {% endprettify %} |
| 1465 </div> |
| 1466 |
| 1467 <div class="trydart-filename">piratebadge.dart</div> |
| 1468 |
| 1469 </div> <div class="span5" markdown="1"> |
| 1470 |
| 1471 * Be sure to remove `final` from these declarations. |
| 1472 |
| 1473 * `[]` is equivalent to `new List()`. |
| 1474 |
| 1475 * A List is a _generic_ type—a List can contain any kind of object. |
| 1476 If you intend for a list to contain only strings, |
| 1477 you can declare it as `List<String>`. |
| 1478 |
| 1479 </div> </div> |
| 1480 |
| 1481 <div class="trydart-step-details" markdown="1"> |
| 1482 |
| 1483 <hr> |
| 1484 |
| 1485 Add two static functions to the PirateName class: |
| 1486 </div> |
| 1487 |
| 1488 <div class="row"> <div class="span7"> |
| 1489 |
| 1490 <div class="trydart-step-details"> |
| 1491 {% prettify dart %} |
| 1492 class PirateName { |
| 1493 ... |
| 1494 |
| 1495 [[highlight]]static Future readyThePirates() { |
| 1496 var path = 'piratenames.json'; |
| 1497 return HttpRequest.getString(path) |
| 1498 .then(_parsePirateNamesFromJSON); |
| 1499 } |
| 1500 |
| 1501 static _parsePirateNamesFromJSON(String jsonString) { |
| 1502 Map pirateNames = JSON.decode(jsonString); |
| 1503 names = pirateNames['names']; |
| 1504 appellations = pirateNames['appellations']; |
| 1505 }[[/highlight]] |
| 1506 } |
| 1507 {% endprettify %} |
| 1508 </div> |
| 1509 |
| 1510 <div class="trydart-filename">piratebadge.dart</div> |
| 1511 |
| 1512 </div> <div class="span5" markdown="1"> |
| 1513 |
| 1514 * `HttpRequest` is a utility for retrieving data from a URL. |
| 1515 |
| 1516 * `getString()` is a convenience method for doing a simple |
| 1517 GET request that returns a string. |
| 1518 |
| 1519 * The code uses a `Future` to perform the GET asynchronously. |
| 1520 |
| 1521 * The callback function for `.then()` is called when |
| 1522 the Future completes successfully. |
| 1523 |
| 1524 * When the Future completes successfully, |
| 1525 the pirate names are read from the JSON file. |
| 1526 |
| 1527 * `readyThePirates` returns the Future so the main program has the |
| 1528 opportunity to do something after the file is read. |
| 1529 |
| 1530 </div> </div> |
| 1531 |
| 1532 <div class="trydart-step-details" markdown="1"> |
| 1533 <hr> |
| 1534 Add a top-level variable. |
| 1535 </div> |
| 1536 |
| 1537 <div class="row"> <div class="span7"> |
| 1538 |
| 1539 <div class="trydart-step-details"> |
| 1540 {% prettify dart %} |
| 1541 [[highlight]]SpanElement badgeNameElement;[[/highlight]] |
| 1542 |
| 1543 void main() { |
| 1544 ... |
| 1545 } |
| 1546 {% endprettify %} |
| 1547 </div> |
| 1548 |
| 1549 <div class="trydart-filename">piratebadge.dart</div> |
| 1550 |
| 1551 </div> <div class="span5" markdown="1"> |
| 1552 |
| 1553 * Stash the span element for repeated use instead of querying the DOM for it. |
| 1554 |
| 1555 </div> </div> |
| 1556 |
| 1557 <div class="trydart-step-details" markdown="1"> |
| 1558 <hr> |
| 1559 Make these changes to the `main()` function. |
| 1560 </div> |
| 1561 |
| 1562 <div class="row"> <div class="span7"> |
| 1563 |
| 1564 <div class="trydart-step-details"> |
| 1565 {% prettify dart %} |
| 1566 void main() { |
| 1567 [[highlight]]InputElement inputField = querySelector('#inputName'); |
| 1568 inputElement.onInput.listen(updateBadge);[[/highlight]] |
| 1569 genButton = querySelector('#generateButton'); |
| 1570 genButton.onClick.listen(generateBadge); |
| 1571 |
| 1572 [[highlight]]badgeNameElement = querySelector('#badgeName');[[/highlight]] |
| 1573 ... |
| 1574 } |
| 1575 {% endprettify %} |
| 1576 </div> |
| 1577 |
| 1578 <div class="trydart-filename">piratebadge.dart</div> |
| 1579 |
| 1580 </div> <div class="span5" markdown="1"> |
| 1581 |
| 1582 * Stash the span element in the global variable. |
| 1583 Also, stash the input element in a local variable. |
| 1584 |
| 1585 |
| 1586 </div> </div> |
| 1587 |
| 1588 <div class="trydart-step-details" markdown="1"> |
| 1589 <hr> |
| 1590 Then, add the code to get the names from the JSON file, |
| 1591 handling both success and failure. |
| 1592 </div> |
| 1593 |
| 1594 <div class="row"> <div class="span7"> |
| 1595 |
| 1596 <div class="trydart-step-details"> |
| 1597 {% prettify dart %} |
| 1598 void main() { |
| 1599 ... |
| 1600 |
| 1601 [[highlight]] PirateName.readyThePirates() |
| 1602 .then((_) { |
| 1603 //on success |
| 1604 inputField.disabled = false; //enable |
| 1605 genButton.disabled = false; //enable[[/highlight]] |
| 1606 setBadgeName(getBadgeNameFromStorage()); |
| 1607 [[highlight]]}) |
| 1608 .catchError((arrr) { |
| 1609 print('Error initializing pirate names: $arrr'); |
| 1610 badgeNameElement.text = 'Arrr! No names.'; |
| 1611 });[[/highlight]] |
| 1612 } |
| 1613 {% endprettify %} |
| 1614 </div> |
| 1615 |
| 1616 <div class="trydart-filename">piratebadge.dart</div> |
| 1617 |
| 1618 </div> <div class="span5" markdown="1"> |
| 1619 |
| 1620 * Call the `readyThePirates()` function, |
| 1621 which returns a Future. |
| 1622 |
| 1623 * When the Future successfully completes, |
| 1624 the `then()` callback function is called. |
| 1625 |
| 1626 * Using underscore (`_`) as a parameter name |
| 1627 indicates that the parameter is ignored. |
| 1628 |
| 1629 * The callback function enables the UI |
| 1630 and gets the stored name. |
| 1631 |
| 1632 * If the Future encounters an error |
| 1633 the `catchError` callback function is called |
| 1634 and the program displays an error message, |
| 1635 leaving the UI disabled. |
| 1636 |
| 1637 * The callback functions for `then()` and `catchError` are defined inline. |
| 1638 |
| 1639 </div> </div> |
| 1640 |
| 1641 #### <i class="icon-anchor"> </i> Run the app. |
| 1642 |
| 1643 <div class="trydart-step-details" markdown="1"> |
| 1644 |
| 1645 Save your files with **File > Save All**. |
| 1646 |
| 1647 Use the Run button |
| 1648 <img src="images/run.png" width="16" height="16" |
| 1649 alt="Run button"> |
| 1650 in Dart Editor to run the app. |
| 1651 |
| 1652 If you want to see what happens when the app can't find the `.json` file, |
| 1653 change the file name in the code and run the program again. |
| 1654 |
| 1655 Compare your app to the final version running below. |
| 1656 |
| 1657 |
| 1658 <iframe class="running-app-frame" |
| 1659 style="height:220px;width:530px;" |
| 1660 src="examples/6-piratebadge_json/piratebadge.html"> |
| 1661 </iframe> |
| 1662 |
| 1663 |
| 1664 ##### Problems? |
| 1665 |
| 1666 Check your code against the files in `6-piratebadge_json`. |
| 1667 |
| 1668 * [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/6-piratebadge_json/piratebadge.html) |
| 1669 |
| 1670 * [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/w
eb/6-piratebadge_json/piratebadge.dart) |
| 1671 |
| 1672 </div> |
| 1673 |
| 1674 {% comment %} |
| 1675 |
| 1676 #### <i class="icon-anchor"> </i> Share your pirate name. |
| 1677 |
| 1678 <div class="trydart-step-details" markdown="1"> |
| 1679 |
| 1680 Congratulations! You finished the pirate badge code lab. |
| 1681 |
| 1682 |
| 1683 Share your pirate name with the world. |
| 1684 |
| 1685 <p class="share-button twitter"> |
| 1686 <a href="https://twitter.com/share" |
| 1687 class="twitter-share-button external-link" |
| 1688 data-count="none" |
| 1689 data-text="Arrr! I've generated me pirate name and learnt Dart, to boot. http
://dartlang.org/darrrt" |
| 1690 data-hashtags="dartlang">Tweet</a> |
| 1691 </p> |
| 1692 |
| 1693 <script src="https://apis.google.com/js/plusone.js"></script> |
| 1694 <g:plus action="share"></g:plus> |
| 1695 |
| 1696 </div> |
| 1697 {% endcomment %} |
| 1698 |
| 1699 |
| 1700 <hr> |
| 1701 |
| 1702 ##Step 7: Go forth and learn more about Dart {#step-seven} |
| 1703 |
| 1704 #### <i class="icon-anchor"> </i> Think about what you've done! |
| 1705 |
| 1706 <div class="trydart-step-details" markdown="1"> |
| 1707 |
| 1708 This code lab provided a tour of most Dart language features |
| 1709 and many library features. |
| 1710 Here's where to go to learn more. |
| 1711 |
| 1712 ##### The Dart language |
| 1713 |
| 1714 <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html"> |
| 1715 A Tour of the Dart Language</a> |
| 1716 shows you how to use each major Dart feature, |
| 1717 from variables and operators to classes and libraries. |
| 1718 This code lab introduced the following Dart language features, |
| 1719 all of which are covered in more detail in the language tour. |
| 1720 |
| 1721 * string interpolation (`'$_firstName the $_appellation'`) |
| 1722 * the cascade operator (`..`) |
| 1723 * the fat arrow (`=>`) function syntax |
| 1724 * the ternary operator (`?:`) |
| 1725 * named constructors (`PirateName.fromJSON(...)`) |
| 1726 * optional parameters |
| 1727 * a class |
| 1728 * getters |
| 1729 * instance methods and fields |
| 1730 * class level methods and fields |
| 1731 * top-level variables and functions |
| 1732 * typecasting with `as` (`(e.target as InputElement)`) |
| 1733 * import, and import with `show` (`import 'dart:math' show Random;`) |
| 1734 * generics |
| 1735 |
| 1736 ##### The Dart libraries |
| 1737 |
| 1738 <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html"> |
| 1739 A Tour of the Dart Libraries</a> |
| 1740 shows you how to use the major features in Dart’s libraries. |
| 1741 |
| 1742 ##### API documentation for classes |
| 1743 |
| 1744 <a href="https://api.dartlang.org/dart_core/String.html" target="_blank">String<
/a>, |
| 1745 <a href="https://api.dartlang.org/dart_core/List.html" target="_blank">List</a>, |
| 1746 <a href="https://api.dartlang.org/dart_core/Map.html" target="_blank">Map</a>, |
| 1747 <a href="https://api.dartlang.org/dart_math/Random.html" target="_blank">Random<
/a>, |
| 1748 <a href="https://api.dartlang.org/dart_html/InputElement.html" target="_blank">I
nputElement</a>, |
| 1749 <a href="https://api.dartlang.org/dart_html/ButtonElement.html" target="_blank">
ButtonElement</a>, |
| 1750 <a href="https://api.dartlang.org/dart_html/Event.html" target="_blank">Event</a
>, |
| 1751 <a href="https://api.dartlang.org/dart_html/HttpRequest.html" target="_blank">Ht
tpRequest</a>, and |
| 1752 <a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Future
</a> |
| 1753 |
| 1754 ##### API documentation for libraries |
| 1755 |
| 1756 <a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a>, |
| 1757 <a href="https://api.dartlang.org/dart_math.html" target="_blank">dart:math</a>, |
| 1758 <a href="https://api.dartlang.org/dart_html.html" target="_blank">dart:html</a>, |
| 1759 <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a
>, and |
| 1760 <a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:conver
t</a> |
| 1761 |
| 1762 ##### API documentation for JSON and local storage |
| 1763 |
| 1764 <a href="https://api.dartlang.org/dart_html/Window.html#localStorage" target="_b
lank">LocalStorage</a>, and |
| 1765 <a href="https://api.dartlang.org/dart_convert.html#JSON" target="_blank">JSON</
a> |
| 1766 |
| 1767 |
| 1768 </div> |
| 1769 |
| 1770 #### <i class="icon-anchor"> </i> Check out the samples. |
| 1771 |
| 1772 <div class="trydart-step-details" markdown="1"> |
| 1773 |
| 1774 Run some Dart programs online and check out the source code |
| 1775 on our [Samples page](/samples/). |
| 1776 </div> |
| 1777 |
| 1778 #### <i class="icon-anchor"> </i> Read the tutorials. |
| 1779 |
| 1780 <div class="trydart-step-details" markdown="1"> |
| 1781 Learn more about Dart from |
| 1782 the [Dart tutorials](/docs/tutorials/). |
| 1783 </div> |
| 1784 |
OLD | NEW |