OLD | NEW |
1 --- | 1 --- |
2 layout: default | 2 layout: default |
3 title: "Get Input from a Form" | 3 title: "Get Input from a Form" |
4 description: "Using HTML forms and input elements to send data to a server" | 4 description: "Using HTML forms and input elements to send data to a server" |
5 has-permalinks: true | 5 has-permalinks: true |
6 tutorial: | 6 tutorial: |
7 id: forms | 7 id: forms |
8 next: indexeddb/ | 8 next: indexeddb/ |
9 next-title: "Use IndexedDB" | 9 next-title: "Use IndexedDB" |
10 prev: fetchdata/ | 10 prev: fetchdata/ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 The main example in this tutorial contains a client and a server. | 63 The main example in this tutorial contains a client and a server. |
64 The client uses Polymer to present its user interface | 64 The client uses Polymer to present its user interface |
65 (a form with many kinds of input elements), | 65 (a form with many kinds of input elements), |
66 and keep the interface in sync with Dart data. | 66 and keep the interface in sync with Dart data. |
67 The client and server communicate using | 67 The client and server communicate using |
68 several classes from the core Dart library, | 68 several classes from the core Dart library, |
69 including streams, Futures, HttpRequest, and so on. | 69 including streams, Futures, HttpRequest, and so on. |
70 The server uses CORS headers to allow cross-origin requests. | 70 The server uses CORS headers to allow cross-origin requests. |
71 | 71 |
| 72 <aside class="alert alert-info" markdown="1"> |
| 73 <strong>Note:</strong> |
| 74 This tutorial assumes that you have read |
| 75 [Define a Custom Elment](/docs/tutorials/polymer-intro/) |
| 76 and [Fetch Data Dynamically](/docs/tutorials/fetchdata/) |
| 77 and are familiar with Polymer, JSON, and HttpRequest. |
| 78 </aside> |
| 79 |
| 80 |
72 * [About forms, generally](#about-forms) | 81 * [About forms, generally](#about-forms) |
73 * [About the slambook example, specifically](#about-the-slambook-example) | 82 * [About the slambook example, specifically](#about-the-slambook-example) |
74 * [Submitting a form](#submitting-a-form) | 83 * [Submitting a form](#submitting-a-form) |
75 * [Resetting a form](#resetting-a-form) | 84 * [Resetting a form](#resetting-a-form) |
76 * [Creating a server and listening on a port](#creating-a-server) | 85 * [Creating a server and listening on a port](#creating-a-server) |
77 * [Handling OPTIONS requests](#handling-options-requests) | 86 * [Handling OPTIONS requests](#handling-options-requests) |
78 * [Setting CORS headers](#setting-cors-headers) | 87 * [Setting CORS headers](#setting-cors-headers) |
79 * [Handling POST requests](#handling-post-requests) | 88 * [Handling POST requests](#handling-post-requests) |
80 * [Recipe for client-server web apps](#recipe) | 89 * [Recipe for client-server web apps](#recipe) |
81 * [Binding data to different kinds of inputs](#binding-data) | 90 * [Two-way data binding using Polymer](#binding-data) |
82 * [Other resources](#other-resources) | 91 * [Other resources](#other-resources) |
| 92 * [What next?](#what-next) |
83 | 93 |
84 ##About forms, generally {#about-forms} | 94 ##About forms, generally {#about-forms} |
85 | 95 |
86 A form has an _action_, which is a URL to which to send the form data, | 96 A form has an _action_, which is a URL to which to send the form data, |
87 and a _method_, which indicates how the form data is to be sent. | 97 and a _method_, which indicates how the form data is to be sent. |
88 The action and the method can be specified declaratively within HTML, | 98 The action and the method can be specified declaratively within HTML, |
89 or for more complex situations or for more control, | 99 or for more complex situations or for more control, |
90 you can write Dart code and use Dart libraries to perform the action | 100 you can write Dart code and use Dart libraries to perform the action |
91 programmatically. | 101 programmatically. |
92 | 102 |
93 Let's begin with a basic, HTML-only form to learn a little bit about | 103 Let's begin with a basic, HTML-only form to learn a little bit about |
94 action, method, input elements, and the default behavior of forms. | 104 action, method, input elements, and the default behavior of forms. |
95 The search_form app running below provides a useful form that | 105 The form below uses Google to search the website |
96 you can add to your website pages. | 106 specified in the <form> tag |
97 It uses Google to search the specified website | 107 if the checkbox is selected |
98 if the checkbox is selected, | 108 (or the web if it is not), |
99 or the web if it is not, | |
100 for the text entered by the user. | 109 for the text entered by the user. |
101 In this example, | 110 In this example, |
102 called `search_form`, | 111 called `search_form`, |
103 the default is to search | 112 the default is to search |
104 [dartlang.org](http://www.dartlang.org) | 113 [dartlang.org](http://www.dartlang.org) |
105 for "Cookbook", | 114 for "Cookbook", |
106 another useful resource for learning about Dart. | 115 a useful resource for learning about Dart. |
107 | 116 |
108 <iframe class="running-app-frame" | 117 <iframe class="running-app-frame" |
109 style="height:100px;width:500px;" | 118 style="height:100px;width:500px;" |
110 src="examples/search_form/web/search_form.html"> | 119 src="examples/search_form/web/search_form.html"> |
111 </iframe> | 120 </iframe> |
112 | 121 |
113 The source code for this example is available on github: | 122 The source code for this example is available on github: |
114 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/for
ms/search_form" | 123 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/for
ms/search_form" |
115 target="_blank">search_form</a>. | 124 target="_blank">search_form</a>. |
116 | 125 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 listens on port 4040 on the local host | 210 listens on port 4040 on the local host |
202 and handles POST and OPTIONS requests | 211 and handles POST and OPTIONS requests |
203 by printing a message and sending a confirmation to the client. | 212 by printing a message and sending a confirmation to the client. |
204 The server uses CORS headers to allow requests from applications | 213 The server uses CORS headers to allow requests from applications |
205 running from a different origin. | 214 running from a different origin. |
206 | 215 |
207 * Second, | 216 * Second, |
208 the client program, | 217 the client program, |
209 called `slambook`, | 218 called `slambook`, |
210 provides a form into which users can enter some information. | 219 provides a form into which users can enter some information. |
211 It uses Polymer data binding to bind the input data to Dart variables. | 220 It uses Polymer two-way data binding to bind the input data to Dart variables. |
212 When the user clicks the submit button, | 221 When the user clicks the submit button, |
213 the Dart code formats the data into a JSON string, | 222 the Dart code formats the data into a JSON string, |
214 sends it to slambookserver using an OPTIONS request to | 223 sends an OPTIONS request to get permission from the server, |
215 get access first and then a POST request to send the data. | 224 and then a POST request to send the data. |
216 When the response from the server is ready, | 225 When the response from the server is ready, |
217 the client displays it. | 226 the client displays it. |
218 | 227 |
219 The following diagram shows the flow of communication between | 228 The following diagram shows the flow of communication between |
220 the server and the client in this example. | 229 the server and the client in this example. |
221 <hr> | 230 <hr> |
222 | 231 |
223  | 232  |
224 | 233 |
225 <hr> | 234 <hr> |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 * Using Polymer to bind the form data to variables in the Dart program | 286 * Using Polymer to bind the form data to variables in the Dart program |
278 | 287 |
279 On the server side, the sections cover | 288 On the server side, the sections cover |
280 | 289 |
281 * CORS headers | 290 * CORS headers |
282 * Handling OPTIONS requests | 291 * Handling OPTIONS requests |
283 * Handling POST requests | 292 * Handling POST requests |
284 | 293 |
285 ##Submitting a form | 294 ##Submitting a form |
286 | 295 |
287 Let's first take a look at how that data is submitted to the server. | 296 Let's first take a look at how the data is submitted to the server. |
288 | 297 |
289 Recall that the search_form example relies on the `action` and | 298 Recall that the search_form example relies on the `action` and |
290 `method` attributes to set the destination and method for the form request. | 299 `method` attributes to set the destination and method for the form request. |
291 Recall also that the search_form example relies | 300 Recall also that the search_form example relies |
292 on the automatic behavior of the special submit button. | 301 on the automatic behavior of the special submit button. |
293 The slambook example, | 302 The slambook example, |
294 on the other hand, | 303 on the other hand, |
295 takes explicit control of the form submission process. | 304 takes explicit control of the form submission process. |
296 | 305 |
297 * First, the form specifies no action or method. | 306 * First, the form specifies no action or method. |
298 * Second, the submit button has a Dart mouse click handler. | 307 * Second, the submit button has a Dart mouse click handler. |
299 * Third, the mouse click handler prevents | 308 * Third, the mouse click handler prevents |
300 the automatic behavior of the submit button. | 309 the automatic behavior of the submit button. |
301 * Finally, the form submits the data to the server | 310 * Finally, the form submits the data to the server |
302 with help from the Dart libraries. | 311 with help from the Dart libraries. |
303 | 312 |
304 The form in the slambook example is | 313 The form in the slambook example is |
305 a custom element called `x-slambook-form` | 314 a custom element called `tute-slambook-form` |
306 that's instantiated with this HTML code: | 315 that's instantiated with this HTML code: |
307 | 316 |
308 {% prettify html %} | 317 {% prettify html %} |
309 <div class="container"> | 318 <div class="container"> |
310 <form is="x-slambook-form" id="slambookform"></form> | 319 <form is="tute-slambook-form" id="slambookform"></form> |
311 </div> | 320 </div> |
312 {% endprettify %} | 321 {% endprettify %} |
313 | 322 |
314 Note the absence of either an `action` or a `method` attribute. | 323 Note the absence of either an `action` or a `method` attribute. |
315 Instead, the behavior for the submit button is coded in Dart. | 324 Instead, the behavior for the submit button is coded in a Dart |
| 325 mouse click handler. |
316 Below is the HTML code that creates the submit button | 326 Below is the HTML code that creates the submit button |
317 and binds it to a Dart mouse click handler. | 327 and binds it to a Dart mouse click handler. |
318 | 328 |
319 {% prettify html %} | 329 {% prettify html %} |
320 <div class="submitarea"> | 330 <div class="submitarea"> |
321 <input type="submit" value="Submit" on-click="submitForm($event)"> | 331 <input type="submit" value="Submit" on-click="submitForm($event)"> |
322 ... | 332 ... |
323 </div> | 333 </div> |
324 {% endprettify %} | 334 {% endprettify %} |
325 | 335 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 // Status is 0...most likely the server isn't running. | 434 // Status is 0...most likely the server isn't running. |
425 serverResponse = 'No server'; | 435 serverResponse = 'No server'; |
426 } | 436 } |
427 } | 437 } |
428 {% endprettify %} | 438 {% endprettify %} |
429 | 439 |
430 First the code checks whether the request is complete and successful. | 440 First the code checks whether the request is complete and successful. |
431 If it is, the code puts the server's response in a string, | 441 If it is, the code puts the server's response in a string, |
432 called `serverResponse`, which is bound to the value of a textarea | 442 called `serverResponse`, which is bound to the value of a textarea |
433 in the slambook app's UI. | 443 in the slambook app's UI. |
434 When the string changes, the UI is automatically updated. | 444 When the string changes, the UI is automatically updated, |
| 445 and the message is displayed for the user. |
435 | 446 |
436 If the request is complete but unsuccessful, | 447 If the request is complete but unsuccessful, |
437 the program sets `serverResponse` to an error message, | 448 the program sets `serverResponse` to an error message, |
438 thus displaying it to the user. | 449 thus displaying it to the user. |
439 | 450 |
440 ##Resetting a form | 451 ##Resetting a form |
441 | 452 |
442 The reset button is a special input type that, by default, | 453 The reset button is a special HTML input type that, by default, |
443 clears the values of all inputs within the form. | 454 clears the values of all inputs within the form. |
444 Currently, | 455 Instead, we want the button to reset the values in the form |
445 this automatic behavior clears the input elements | 456 to their initial value. |
446 as expected, | |
447 but any bound Dart values do not get updated. | |
448 | |
449 So, the mouse click handler for the reset button | 457 So, the mouse click handler for the reset button |
450 needs to suppress the automatic behavior | 458 needs to suppress the automatic behavior |
451 and reset the form with neutral data explicitly. | 459 and reset the form with neutral data explicitly. |
452 | 460 |
453 {% prettify dart %} | 461 {% prettify dart %} |
454 void resetForm(Event e) { | 462 void resetForm(Event e) { |
455 e.preventDefault(); | 463 e.preventDefault(); |
456 favoriteThings['kittens'] = false; | 464 favoriteThings['kittens'] = false; |
457 favoriteThings['raindrops'] = false; | 465 favoriteThings['raindrops'] = false; |
458 favoriteThings['mittens'] = false; | 466 favoriteThings['mittens'] = false; |
459 favoriteThings['kettles'] = false; | 467 favoriteThings['kettles'] = false; |
460 | 468 |
461 theData['firstName'] = ''; | 469 theData['firstName'] = ''; |
462 theData['favoriteQuote'] = ''; | 470 theData['favoriteQuote'] = ''; |
463 theData['favoriteColor'] = '#FFFFFF'; | 471 theData['favoriteColor'] = '#FFFFFF'; |
464 theData['birthday'] = '2013-01-01'; | 472 theData['birthday'] = '2013-01-01'; |
465 theData['volume'] = '0'; | 473 theData['volume'] = '0'; |
466 theData['catOrDog'] = 'cat'; | 474 theData['catOrDog'] = 'cat'; |
467 theData['music'] = 0; | 475 theData['music'] = 0; |
468 theData['zombies'] = false; | 476 theData['zombies'] = false; |
469 serverResponse = "Data cleared."; | 477 serverResponse = "Data reset."; |
470 } | 478 } |
471 {% endprettify %} | 479 {% endprettify %} |
472 | 480 |
473 ##Creating a server and listening on a port {#creating-a-server} | 481 ##Creating a server and listening on a port {#creating-a-server} |
474 | 482 |
475 Let's turn our attention now to the server, called `slambookserver`, | 483 Let's turn our attention now to the server, called `slambookserver`, |
476 that responds to HTTP requests from the slambook client. | 484 that responds to HTTP requests from the slambook client. |
477 The code for the server is based | 485 The code for the server is based |
478 on the one in Chris Buckett's article | 486 on the one in Chris Buckett's article |
479 <a href="/articles/json-web-service/">Using Dart with JSON Web Services</a>. | 487 <a href="/articles/json-web-service/">Using Dart with JSON Web Services</a>. |
(...skipping 27 matching lines...) Expand all Loading... |
507 | 515 |
508 The bind() function returns a Future object, | 516 The bind() function returns a Future object, |
509 which is a way to get a value in the future (more about that in a minute). | 517 which is a way to get a value in the future (more about that in a minute). |
510 Using then(), | 518 Using then(), |
511 the code registers two callback functions on the Future. | 519 the code registers two callback functions on the Future. |
512 The first, gotMessage(), is called when the Future returns its value. | 520 The first, gotMessage(), is called when the Future returns its value. |
513 The second, `printError`, is called if the binding fails. | 521 The second, `printError`, is called if the binding fails. |
514 An error might occur if, for example, | 522 An error might occur if, for example, |
515 another program is already listening on the same port. | 523 another program is already listening on the same port. |
516 | 524 |
517 The code for gotMessage(), shown below, triages the request | 525 The code for gotMessage(), shown below, filters the request |
518 and calls other methods to handle each specific kind of request. | 526 and calls other methods to handle each specific kind of request. |
519 | 527 |
520 {% prettify dart %} | 528 {% prettify dart %} |
521 void gotMessage(_server) { | 529 void gotMessage(_server) { |
522 _server.listen((HttpRequest request) { | 530 _server.listen((HttpRequest request) { |
523 switch (request.method) { | 531 switch (request.method) { |
524 case 'POST': | 532 case 'POST': |
525 handlePost(request); | 533 handlePost(request); |
526 break; | 534 break; |
527 case 'OPTIONS': | 535 case 'OPTIONS': |
528 handleOptions(request); | 536 handleOptions(request); |
529 break; | 537 break; |
530 default: defaultHandler(request); | 538 default: defaultHandler(request); |
531 } | 539 } |
532 }, | 540 }, |
533 onError: printError); // Listen failed. | 541 onError: printError); // Listen failed. |
534 print('Listening for GET and POST on http://$HOST:$PORT'); | 542 print('Listening for GET and POST on http://$HOST:$PORT'); |
535 } | 543 } |
536 {% endprettify %} | 544 {% endprettify %} |
537 | 545 |
538 To handle other types of requests, | 546 To handle other types of requests |
539 you could simply add more `case` statements. | 547 such as `GET` requests, |
540 For example, `case 'GET'` for HTTP GET requests. | 548 you could simply add more `case` statements, |
| 549 such as `case 'GET'`. |
541 | 550 |
542 ###About Futures, briefly | 551 ###About Futures, briefly |
543 | 552 |
544 Let's take a brief look at Futures before we check out the code | 553 Let's take a brief look at Futures before we check out the code |
545 for handling OPTIONS and POST requests. | 554 for handling OPTIONS and POST requests. |
546 | 555 |
547 A | 556 A |
548 <a href="https://api.dartlang.org/dart_async/Future.html" | 557 <a href="https://api.dartlang.org/dart_async/Future.html" |
549 target="_blank">Future</a> | 558 target="_blank">Future</a> |
550 represents a way to get a value sometime in the Future. | 559 represents a way to get a value sometime in the Future. |
551 You use Futures to avoid blocking the program | 560 You use Futures to avoid blocking the program |
552 while waiting for a value—for example, | 561 while waiting for a value—for example, |
553 if the value requires a long time to compute, | 562 if the value requires a long time to compute, |
554 or if the value must be read or retrieved using I/O. | 563 or if the value must be read or retrieved using I/O. |
555 | 564 |
556 When a function that returns a Future is invoked, | 565 When a function that returns a Future is invoked, |
557 two things happen: | 566 two things happen: |
558 | 567 |
559 <ul> | 568 <ul> |
560 <li> | 569 <li> |
561 The function queues up work to be done | 570 The function queues up work to be done |
562 and returns an uncompleted Future object immediately. | 571 and returns an uncompleted Future object immediately. |
563 </li> | 572 </li> |
564 <li> | 573 <li> |
565 Later, when a value is available, | 574 Later, when the value is available, |
566 the Future object completes with that value or with an error. | 575 the Future object completes with that value or with an error. |
567 </li> | 576 </li> |
568 </ul> | 577 </ul> |
569 | 578 |
570 To get the value that the Future represents, | 579 To get the value that the Future represents, |
571 use the then() method to register a callback. | 580 use the then() method to register a callback. |
572 When the Future completes, it calls | 581 When the Future completes, it calls |
573 the callback function. | 582 the callback function. |
574 | 583 |
575 In this example, | 584 In this example, |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 and one in dart:io (for servers). | 747 and one in dart:io (for servers). |
739 | 748 |
740 | Resource | Library | Description | | 749 | Resource | Library | Description | |
741 |---|---| | 750 |---|---| |
742 | <a href="https://api.dartlang.org/dart_html/HttpRequest.html" target="_blank">
HttpRequest</a> | dart:html | Client-side HTTP request | | 751 | <a href="https://api.dartlang.org/dart_html/HttpRequest.html" target="_blank">
HttpRequest</a> | dart:html | Client-side HTTP request | |
743 | <a href="https://api.dartlang.org/dart_io/HttpRequest.html" target="_blank">Ht
tpRequest</a> | dart:io | Server-side HTTP request | | 752 | <a href="https://api.dartlang.org/dart_io/HttpRequest.html" target="_blank">Ht
tpRequest</a> | dart:io | Server-side HTTP request | |
744 | <a href="https://api.dartlang.org/dart_io/HttpServer.html" target="_blank">Htt
pServer</a> | dart:io | Server-side object to handle HTTP communication with cli
ents | | 753 | <a href="https://api.dartlang.org/dart_io/HttpServer.html" target="_blank">Htt
pServer</a> | dart:io | Server-side object to handle HTTP communication with cli
ents | |
745 | <a href="https://api.dartlang.org/dart_io/HttpResponse.html" target="_blank">H
ttpResponse</a> | dart:io | Server-side object to carry response to client reque
sts | | 754 | <a href="https://api.dartlang.org/dart_io/HttpResponse.html" target="_blank">H
ttpResponse</a> | dart:io | Server-side object to carry response to client reque
sts | |
746 | <a href="https://api.dartlang.org/dart_async/Stream.html" target="_blank">Stre
ams</a> | dart:async | A stream of data | | 755 | <a href="https://api.dartlang.org/dart_async/Stream.html" target="_blank">Stre
ams</a> | dart:async | A stream of data | |
747 | <a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Futu
re</a> | dart:async | A way to get a value asynchronously | | 756 | <a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Futu
re</a> | dart:async | A way to get a value asynchronously | |
748 | <a href="https://api.dartlang.org/dart_json.html" target="_blank">stringify()<
/a> | dart:json | How you format an object into a JSON string | | 757 | <a href="https://api.dartlang.org/dart_json.html" target="_blank">stringify()<
/a> | dart:convert | A library with resources for converting an object into a JS
ON string | |
749 | <a href="https://api.dartlang.org/polymer.html" target="_blank">Polymer</a> |
Polymer | Custom elements, data binding, templates | | 758 | <a href="https://api.dartlang.org/polymer.html" target="_blank">Polymer</a> |
Polymer | Custom elements, data binding, templates | |
750 {: .table} | 759 {: .table} |
751 | 760 |
752 ##Binding data to different kinds of inputs {#binding-data} | 761 ##Two-way data binding using Polymer {#binding-data} |
753 | 762 |
754 The slambook sample uses Polymer to | 763 The slambook sample uses Polymer's two-way data binding to |
755 bind the values of input elements to Dart variables. | 764 bind the values of input elements to Dart variables. |
756 If the user changes the value in an input element, | 765 If the user changes the value in an input element, |
757 the bound variable in the Dart code automatically changes. | 766 the bound variable in the Dart code automatically changes. |
758 Or if the Dart code changes the value of the bound variable, | 767 Or if the Dart code changes the value of the bound variable, |
759 the UI automatically updates. | 768 the UI automatically updates. |
760 [Define a Custom Element](/docs/tutorials/polymer-intro/) | 769 [Define a Custom Element](/docs/tutorials/polymer-intro/) |
761 provides introductory details | 770 provides introductory details about Polymer and |
762 about data binding with Polymer. | 771 about data binding. |
763 | 772 |
764 With this example, | 773 The example also uses declarative event handler mapping to hook |
| 774 event handler functions to input elements. |
| 775 |
| 776 With the slambook example, |
765 you can see two-way data binding used with a variety of input elements, | 777 you can see two-way data binding used with a variety of input elements, |
766 including new HTML5 elements. | 778 including new HTML5 elements. |
767 This table summarizes the two-way data binding attributes | 779 This table summarizes the two-way data binding attributes |
768 you can use with Polymer: | 780 you can use with Polymer: |
769 | 781 |
770 | Attribute | Dart type | Input element | | 782 | Attribute | Dart type | Input element | |
771 |---|---| | 783 |---|---| |
772 | bind-value | String | any <br>with special considerations for elements <br> th
at allow multiple selection,<br> such as a group of radio buttons and <select
> elements | | 784 | value | String | any | |
773 | bind-selected-index | integer | a <select> element in which only one cho
ice is allowed | | 785 | selectedIndex | integer | a <select> element in which only one choice is
allowed | |
774 | bind-checked | bool | individual radio buttons or checkboxes | | 786 | checked | bool | individual radio buttons or checkboxes | |
775 {: .table .nowraptable} | 787 {: .table} |
776 | 788 |
777 ###Using bind-value with any input element | 789 ###Using value with any input element |
778 | 790 |
779 The `bind-value` attribute works with any input element | 791 The `value` attribute works with any input element |
780 and binds the value to a Dart string. | 792 and binds the value to a Dart string. |
781 This example uses `bind-value` with a text field, a text area, | 793 This example uses `value` with a text field, a text area, |
782 a color picker, a date chooser, and a range element. | 794 a color picker, a date chooser, and a range element. |
783 | 795 |
784  | 796  |
785 | 797 |
786 (Note that some surrounding code, | 798 (Note that some surrounding code, |
787 such as that for the labels, | 799 such as that for the labels, |
788 has been removed for readability.) | 800 has been removed for readability.) |
789 | 801 |
790 A map called `theData` in the Dart code contains the data for the form. | 802 A map called `theData` in the Dart code contains the data for the form. |
791 The code marks the map object with `@observable` and calls `toObservable()` | 803 The code marks the map object with `@observable` and calls `toObservable()` |
792 to make the bindings. | 804 to make the bindings. |
793 | 805 |
794 The map contains a key-value pair for each input element, | 806 The map contains a key-value pair for each input element, |
795 where the key is a string. | 807 where the key is a string. |
796 The values in the map can be of any type | 808 The values for elements bound with `value` are all strings. |
797 but the values for elements bound with `bind-value` are all strings. | |
798 The HTML refers to the items in the map | 809 The HTML refers to the items in the map |
799 using their Dart names (identifiers). | 810 using their Dart names (identifiers). |
800 For example, the value of the color picker is bound to | 811 For example, the value of the color picker is bound to |
801 `theData['favoriteColor']`. | 812 `theData['favoriteColor']`. |
802 | 813 |
| 814 {% comment %} |
803 ####Special case: Using bind-value with a group of radio buttons | 815 ####Special case: Using bind-value with a group of radio buttons |
804 | 816 |
805 The slambook form contains three radio buttons, | 817 The slambook form contains three radio buttons, |
806 which together make a group | 818 which together make a group |
807 because they all have the same name, `catOrDog`. | 819 because they all have the same name, `catOrDog`. |
808 All of the radio buttons are bound to the same string. | 820 All of the radio buttons are bound to the same string. |
809 Because only one radio button in a group can be selected at a time | 821 Because only one radio button in a group can be selected at a time |
810 and each radio button has a different value, | 822 and each radio button has a different value, |
811 the bound string reflects the value of the entire group. | 823 the bound string reflects the value of the entire group. |
812 | 824 |
813  | 825  |
814 | 826 |
815 {% comment %} | |
816 ####Special case: Not using bind-value with a multiple select element | 827 ####Special case: Not using bind-value with a multiple select element |
817 | 828 |
818 By default a <select> element allows | 829 By default a <select> element allows |
819 only one option to be selected at a time. | 830 only one option to be selected at a time. |
820 For a single selection <select> element, | 831 For a single selection <select> element, |
821 use bind-selected-index (explained below) | 832 use bind-selected-index (explained below) |
822 to get the index of the selected option. | 833 to get the index of the selected option. |
823 If you want to allow the user to select multiple options, | 834 If you want to allow the user to select multiple options, |
824 use the `multiple` attribute. | 835 use the `multiple` attribute. |
825 | 836 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 that dynamically creates a List object containing the keys | 913 that dynamically creates a List object containing the keys |
903 to the selected books. | 914 to the selected books. |
904 | 915 |
905  | 916  |
906 | 917 |
907 The `booksselected` getter has an implied dependency on | 918 The `booksselected` getter has an implied dependency on |
908 the `books` map, because the getter uses the map. | 919 the `books` map, because the getter uses the map. |
909 When `books` changes, the UI updates the unnumbered list of selected books. | 920 When `books` changes, the UI updates the unnumbered list of selected books. |
910 {% endcomment %} | 921 {% endcomment %} |
911 | 922 |
912 ###Using bind-selected-index with a pull-down menu | 923 ###Using selectedIndex with a pull-down menu |
913 | 924 |
914 A <select> element contains one or more <option> elements, | 925 A <select> element contains one or more <option> elements, |
915 only one of which, by default, can be selected at a time. | 926 only one of which, by default, can be selected at a time. |
916 A single-select element is usually implemented as a pull-down menu. | 927 A single-select element is usually implemented as a pull-down menu. |
917 You can use the `bind-selected-index` attribute | 928 You can use the `selectedIndex` attribute |
918 to bind a Dart integer to a pull-down menu. | 929 to bind a Dart integer to a pull-down menu. |
919 The integer indicates the index of the selected item. | 930 The integer indicates the index of the selected item. |
920 Indices begin at 0. | 931 Indices begin at 0. |
921 | 932 |
922  | 933  |
923 | 934 |
924 ###Using bind-checked with checkboxes | 935 ###Using checked with checkboxes |
925 | 936 |
926 You can use the `bind-checked` attribute | 937 You can use the `checked` attribute |
927 to bind a Dart boolean to a single checkbox. | 938 to bind a Dart boolean to a single checkbox. |
928 Here each checkbox is bound to a separate boolean value within a map. | 939 Here each checkbox is bound to a separate boolean value within a map. |
929 | 940 |
930  | 941  |
931 | 942 |
932 | 943 |
933 ##Other resources | 944 ##Other resources |
934 | 945 |
935 <ul> | 946 <ul> |
936 <li> The code that handles the communication between the | 947 <li> The code that handles the communication between the |
937 client and server is based on code written and explained | 948 client and server is based on code written and explained |
938 by Chris Buckett in | 949 by Chris Buckett in |
939 <a href="/articles/json-web-service/">Using Dart with JSON Web Services</
a>. | 950 <a href="/articles/json-web-service/">Using Dart with JSON Web Services</
a>. |
940 </li> | 951 </li> |
941 <li> Check out | 952 <li> Check out |
942 <a href="/docs/cookbook/"> | 953 <a href="/docs/cookbook/"> |
943 <i class="icon-food"> </i> Dart Cookbook</a>. | 954 <i class="icon-food"> </i> Dart Cookbook</a>. |
944 You'll find many recipes related to topics in this tutorial, | 955 You'll find many recipes related to topics in this tutorial, |
945 including JSON and URIs. | 956 including JSON and URIs. |
946 </li> | 957 </li> |
947 <li> The previous tutorial, | 958 <li> The previous tutorial, |
948 <a href="/docs/tutorials/fetchdata/">Fetch Data Dynamically</a>, | 959 <a href="/docs/tutorials/fetchdata/">Fetch Data Dynamically</a>, |
949 contains a more basic client program that relies on the server | 960 contains a more basic client program that relies on the server |
950 within Dart Editor (port 3030 on localhost), | 961 within Dart Editor (port 3030 on localhost), |
951 to serve the contents of a JSON file. | 962 to serve the contents of a JSON file. |
952 </li> | 963 </li> |
953 </ul> | 964 </ul> |
954 | 965 |
955 ###What next? | 966 ###What next? |
956 | 967 |
957 Try our | 968 The next tutorial, |
958 <a href="/codelabs/web-ui-writer/index.html" target="_blank"><i class="icon-beak
er"> </i>Codelab</a>. | 969 [Use IndexedDB](/docs/tutorials/indexeddb), |
959 In this step-by-step guide, you’ll build a simple, | 970 describes how to save data on the client |
960 single-page, modern web app for desktop and mobile. | 971 in the browser's Indexed Database. |
961 | 972 |
962 {% endcapture %} | 973 {% endcapture %} |
963 | 974 |
964 {% include tutorial.html %} | 975 {% include tutorial.html %} |
OLD | NEW |