| OLD | NEW |
| (Empty) |
| 1 --- | |
| 2 layout: default | |
| 3 title: "Use Templates" | |
| 4 description: "Use template loops and conditionals for declarative UI creation." | |
| 5 has-permalinks: true | |
| 6 tutorial: | |
| 7 id: web-ui-templates | |
| 8 next: custom-elements/ | |
| 9 next-title: "Define a Custom DOM Tag" | |
| 10 prev: web-ui/ | |
| 11 prev-title: "Get Started with Web UI" | |
| 12 --- | |
| 13 | |
| 14 {% capture whats_the_point %} | |
| 15 | |
| 16 * The Web UI package implements templates in HTML. | |
| 17 * You can conditionally activate DOM elements declaratively. | |
| 18 * Use template loops to create UI elements from a Dart Iterable. | |
| 19 | |
| 20 {% endcapture %} | |
| 21 | |
| 22 {% capture sample_links %} | |
| 23 | |
| 24 <p> | |
| 25 Get the source code for the samples featured in this target:</p> | |
| 26 | |
| 27 <ul> | |
| 28 <li> | |
| 29 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
/target07/adlibitum" | |
| 30 target="_blank">adlibitum</a> | |
| 31 </li> | |
| 32 <li> | |
| 33 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
/target07/simplehangman" | |
| 34 target="_blank">simplehangman</a> | |
| 35 </li> | |
| 36 <li> | |
| 37 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web
/target07/hangman" | |
| 38 target="_blank">hangman</a> | |
| 39 </li> | |
| 40 </ul> | |
| 41 | |
| 42 {% endcapture %} | |
| 43 | |
| 44 {% capture content %} | |
| 45 | |
| 46 <div class="tute-target-title"> | |
| 47 <h1>{{page.title}}</h1> | |
| 48 <h3>Create dynamic elements declaratively.</h3> | |
| 49 </div> | |
| 50 | |
| 51 <hr> | |
| 52 | |
| 53 <aside class="alert" style="background-color:Lavender;color:SlateBlue"> | |
| 54 <font size="24"> | |
| 55 <i class="icon-bullhorn"> </i> | |
| 56 </font> | |
| 57 Web UI is being upgraded to polymer.dart. | |
| 58 For more information about polymer.dart, | |
| 59 including tips on porting Web UI apps to polymer.dart | |
| 60 and the current status of the project, | |
| 61 check out the <a href="/polymer-dart/" target="_blank">polymer.dart</a> | |
| 62 home page. | |
| 63 For polymer.dart versions of the tutorial's Web UI apps, | |
| 64 check out the tutorial's | |
| 65 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/" | |
| 66 target="_blank">code repo</a> on github. | |
| 67 </aside> | |
| 68 | |
| 69 <hr> | |
| 70 | |
| 71 The Web UI package implements the <template> tag, | |
| 72 which you can use directly in your HTML. | |
| 73 Templates define UI elements that are instantiated | |
| 74 only under specific circumstances. | |
| 75 You can use templates to define the structure of a custom element, | |
| 76 to instantiate UI elements based on a boolean condition, | |
| 77 or to repeat UI elements by iterating over a Dart Iterable object. | |
| 78 | |
| 79 This target covers | |
| 80 template conditionals and loops, | |
| 81 both of which provide a declarative way | |
| 82 to add and remove UI elements. | |
| 83 The next target, | |
| 84 <a href="/docs/tutorials/custom-elements/">Target 8: Define a Custom DOM Tag</a>
, | |
| 85 covers custom elements | |
| 86 and how to use templates to define their structure. | |
| 87 | |
| 88 * [Using conditional instantiation](#using-conditional-instantiation) | |
| 89 * [Using iteration with templates](#using-iteration-with-templates) | |
| 90 * [Using iteration with other elements](#as-attributes) | |
| 91 * [Other resources](#other-resources) | |
| 92 | |
| 93 ##Using conditional instantiation | |
| 94 | |
| 95 In the example application running below, | |
| 96 you provide six words to fill in the blanks of a hidden text. | |
| 97 Try it! Type six items into the input fields. | |
| 98 The results appear only after you have entered a value for all six items. | |
| 99 After you've entered all six items, delete one. The paragraph disappears. | |
| 100 | |
| 101 <iframe class="running-app-frame" | |
| 102 style="height:300px;width:300px;" | |
| 103 src="http://dart-lang.github.io/dart-tutorials-samples/web/target07/adli
bitum/web/out/adlibitum.html"> | |
| 104 </iframe> | |
| 105 | |
| 106 You can find the complete source code for this sample on github at | |
| 107 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/tar
get07/adlibitum" target="_blank">adlibitum</a>. | |
| 108 | |
| 109 The sample uses a template conditional | |
| 110 to display the paragraphs under the input fields. | |
| 111 | |
| 112  | |
| 113 | |
| 114 The value of each input field is bound to an observable Dart String | |
| 115 using two-way data binding as described in the | |
| 116 <a href="/docs/tutorials/web-ui/">previous target</a>. | |
| 117 The binding keeps the value of each input field in sync with | |
| 118 the value of a Dart string as the user types. | |
| 119 | |
| 120  | |
| 121 | |
| 122 The paragraph underneath the six input fields appears | |
| 123 if all input fields have a value. | |
| 124 Together, a template conditional in the HTML code | |
| 125 and an observable boolean getter in the Dart code | |
| 126 determine when to display the paragraph. | |
| 127 The Dart code contains a getter called `show` | |
| 128 that returns true if all of the fields have a value | |
| 129 or false if one or more is empty. | |
| 130 Observables determine that `show` depends on the six strings, | |
| 131 and notify a change on `show` if any strings change. | |
| 132 | |
| 133  | |
| 134 | |
| 135 The template is declared with the <template> tag. | |
| 136 The template tag has an `instantiate` attribute, | |
| 137 which contains the expression | |
| 138 that determines whether the template should be activated or deactivated. | |
| 139 | |
| 140 The instantiate attribute takes the form `if exp`, | |
| 141 where `exp` is a valid Dart expression | |
| 142 that evaluates to either true or false. | |
| 143 In this example, | |
| 144 the expression is a call to a top-level getter. | |
| 145 When the expression is true, | |
| 146 the contents of the template are instantiated. | |
| 147 Otherwise, any elements that were previously instantiated | |
| 148 are removed from the DOM. | |
| 149 | |
| 150 In this example, | |
| 151 the conditional template just contains simple paragraph elements | |
| 152 in which some of the text is bound to the values in input fields. | |
| 153 | |
| 154 ##Using iteration with templates | |
| 155 | |
| 156 The sample running below | |
| 157 is a simplified version of the children's hangman game. | |
| 158 Try it! Type letters in the field to guess the word. | |
| 159 | |
| 160 <iframe class="running-app-frame" | |
| 161 style="height:250px;width:300px;" | |
| 162 src="http://dart-lang.github.io/dart-tutorials-samples/web/target07/simp
lehangman/web/out/simplehangman.html"> | |
| 163 </iframe> | |
| 164 | |
| 165 You can find the complete source code for this sample on github at | |
| 166 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/tar
get07/simplehangman" target="_blank">simplehangman</a>. | |
| 167 | |
| 168 The hangman example uses template iteration in two places: | |
| 169 to reveal the correctly guessed letters in the | |
| 170 hyphenated version of the hidden word | |
| 171 and to display the list of incorrectly guessed letters. | |
| 172 | |
| 173  | |
| 174 | |
| 175 The Dart code creates two lists, | |
| 176 one for the hyphenated word and one for the incorrectly guessed letters. | |
| 177 Each list contains strings. | |
| 178 Each string contains a single hyphen or letter. | |
| 179 The program calls `toObservable()` on each list | |
| 180 to make Web UI track changes to the list. | |
| 181 | |
| 182 {% prettify dart %} | |
| 183 List<String> hyphens = toObservable(answerHyphenated.split('')); | |
| 184 List<String> wrongletters = toObservable(new List()); | |
| 185 {% endprettify %} | |
| 186 | |
| 187 In the HTML code, | |
| 188 a template loop iterates over the list named `hyphens` | |
| 189 to reveal each letter of the word when it is correctly guessed. | |
| 190 Another template loop iterates over the list named `wrongletters` | |
| 191 to display the incorrectly guessed letters. | |
| 192 | |
| 193 {% prettify html %} | |
| 194 <template iterate="character in hyphens"> {% raw %}{{character}}{% endraw %} </t
emplate> | |
| 195 ... | |
| 196 <template iterate="wrongchar in wrongletters"> {% raw %}{{wrongchar}}{% endraw
%} </template> | |
| 197 {% endprettify %} | |
| 198 | |
| 199 When the user types a character, | |
| 200 the event handler for the input field either adds a letter to `wrongletters` | |
| 201 or reveals a letter in `hyphens`. | |
| 202 Because these lists are observable, | |
| 203 a change causes the associated template loop | |
| 204 to re-evaluate and to update the UI. | |
| 205 The following diagram shows the relationship between | |
| 206 the Dart code, the HTML code, and the UI | |
| 207 that manages the list of incorrectly guessed letters. | |
| 208 | |
| 209  | |
| 210 | |
| 211 The <template> tag has an attribute called `iterate`. | |
| 212 The value of this attribute takes the form | |
| 213 <code><em>loopvar</em> in <em>iterable</em></code>, | |
| 214 where _iterable_ is a Dart expression that evaluates to an | |
| 215 <a href="https://api.dartlang.org/dart_core/Iterable.html" | |
| 216 target="_blank">Iterable</a> | |
| 217 object. | |
| 218 The template iterates over the iterable object | |
| 219 and assigns each value to _loopvar_, | |
| 220 a new variable that is in scope for the body of the template iterate element. | |
| 221 The HTML code for this example | |
| 222 uses one-way data binding to embed | |
| 223 the value of `wrongchar` in the page, | |
| 224 thus displaying a list of characters. | |
| 225 | |
| 226 ##Using iteration with other elements {#as-attributes} | |
| 227 | |
| 228 The simplehangman example used the iterate attribute on a template node. | |
| 229 You can use `template iterate` as an attribute on any type of element. | |
| 230 This is particularly useful in tables | |
| 231 because you cannot use templates in tables. | |
| 232 In the future, the Web UI team intends to remove the extra `template` | |
| 233 attribute, and you will be able to use just `iterate` directly | |
| 234 on elements as well as on templates. | |
| 235 | |
| 236 Here's a new version of the hangman example. | |
| 237 Try it! Guess the word. | |
| 238 | |
| 239 <iframe class="running-app-frame" | |
| 240 style="height:250px;width:350px;" | |
| 241 src="http://dart-lang.github.io/dart-tutorials-samples/web/target07/hang
man/web/out/hangman.html"> | |
| 242 </iframe> | |
| 243 | |
| 244 You can find the complete source code for this sample on github at | |
| 245 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/tar
get07/hangman" target="_blank">hangman</a>. | |
| 246 | |
| 247 The gallows is displayed using a table. | |
| 248 The table uses `template iterate` as an attribute on | |
| 249 the table body and on the table row to | |
| 250 display the characters in the hangman display. | |
| 251 | |
| 252  | |
| 253 | |
| 254 The data for the gallows is contained on the Dart side | |
| 255 in a list of lists called `hangmandisplay`. | |
| 256 Each sublist is a list of strings, each of which | |
| 257 contains a single character. | |
| 258 So each string represents a cell in the table. | |
| 259 The top-level function setUpHangmanGrid() populates | |
| 260 the list of lists with this code: | |
| 261 | |
| 262 {% prettify dart %} | |
| 263 List<List> hangmandisplay; | |
| 264 | |
| 265 void setUpHangmanGrid() { | |
| 266 var gallows = [ '+---+ ', | |
| 267 '\| ', | |
| 268 '\| ', | |
| 269 '\| ', | |
| 270 '\| ' ]; | |
| 271 hangmandisplay = new List(gallows.length); | |
| 272 | |
| 273 for (int i = 0; i < gallows.length; i++) { | |
| 274 List<String> row = gallows[i].split(""); | |
| 275 hangmandisplay[i] = toObservable(row); | |
| 276 } | |
| 277 } | |
| 278 {% endprettify %} | |
| 279 | |
| 280 To create the table in HTML, | |
| 281 one template loop iterates over of the hangmandisplay list of lists, | |
| 282 using each sublist for a row in the table. | |
| 283 The second template loop iterates over each sublist (a list of strings) | |
| 284 using each string for a cell in the table. | |
| 285 | |
| 286  | |
| 287 | |
| 288 `hangmandisplay` is the Dart data to iterate over. | |
| 289 `row` and `cell` are both temporary loop variables. | |
| 290 | |
| 291 The contents of the hangmandisplay are changed programmatically | |
| 292 for each incorrectly guessed letter in a top-level function called | |
| 293 revealnewbodypart(). | |
| 294 | |
| 295 When the user guesses a letter, | |
| 296 the change event handler is called. | |
| 297 If the guess is incorrect, | |
| 298 the contents of the hangmandisplay are modified. | |
| 299 As a result of the change event, | |
| 300 the observables are re-evaluated and | |
| 301 the gallows UI is updated. | |
| 302 | |
| 303 ##Other resources | |
| 304 | |
| 305 <ul> | |
| 306 <li> | |
| 307 Another use of the <template> tag | |
| 308 is to define the contents of a custom element. | |
| 309 The next target, | |
| 310 <a href="/docs/tutorials/custom-elements/">Define a Custom DOM Tag</a>, | |
| 311 provides an example that converts numbers based on a simple ratio. | |
| 312 </li> | |
| 313 <li> Check out | |
| 314 <a href="/docs/cookbook/"> | |
| 315 <i class="icon-food"> </i> Dart Cookbook</a>. | |
| 316 You'll find several | |
| 317 <a href="/docs/cookbook/#web-ui">Web UI recipes</a>. | |
| 318 </li> | |
| 319 <li> | |
| 320 Sigmund Cherem's article, | |
| 321 <a href="/articles/dart-web-components/">Web UI Package</a>, | |
| 322 contains several interactive examples on the page | |
| 323 and the corresponding source code. | |
| 324 </li> | |
| 325 </ul> | |
| 326 | |
| 327 {% endcapture %} | |
| 328 | |
| 329 {% include tutorial.html %} | |
| OLD | NEW |