UNPKG

3.5 kBMarkdownView Raw
1# Conditionals and Lists
2
3While HTML itself does not support conditionally displaying elements or repeating elements, it is a critical part of building any web application. In Marko, this functionality is provided by the `<if>` and `<for>` tags.
4
5## Conditionals
6
7The `<if>` tag recieves an [argument](./syntax.md#arguments) which is used to determine if its body content should be present.
8
9```marko
10<if(user.loggedOut)>
11 <a href="/login">Log in</a>
12</if>
13```
14
15As you might expect, there are also `<else>` and `<else-if>` tags as well:
16
17```marko
18<if(user.loggedOut)>
19 <a href="/login">Log in</a>
20</if>
21<else-if(!user.trappedForever)>
22 <a href="/logout">Log out</a>
23</else-if>
24<else>
25 Hey ${user.name}!
26</else>
27```
28
29## Lists
30
31If you have a list of data and need to represent it in the UI, the `<for>` tag is probably what you're looking for. The `<for>` tag passes each item and its index to its body as [parameters](./syntax.md#parameters).
32
33```marko
34<ul>
35 <for|color, index| of=colors>
36 <li>${index}: ${color}</li>
37 </for>
38</ul>
39```
40
41The `<for>` tag actually support 3 different flavors:
42
43- [`<for|item, index, array| of=array>`](./core-tags.md#iterating-over-a-list) renders its body for each item of an array. It's similar to the JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.
44- [`<for|key, value| in=object>`](./core-tags.md#iterating-over-an-objects-properties) renders its body for each property in an object. It's similar to the JavaScript [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop.
45- [`<for|value| from=first to=last step=increment>`](./core-tags.md#iterating-between-a-range-of-numbers) renders its body for each value in between and including `from` and `to`.
46
47### Always set a `key`
48
49Marko automatically keeps your UI in sync with the state behind it, but one place where it needs a little extra help is repeated content. Specifying keys gives Marko a way to identify items in a list and keep track of which items have been changed, added, or removed.
50
51A key should be a string or number that uniquely identifies an item in the list and differentiates it from its siblings. The same key value should never be used twice! Often, you will use something like an `id` property.
52
53```marko
54<for|user| of=users>
55 <user-card key=user.id data=user/>
56</for>
57```
58
59> **ProTip:** If you have multiple tags underneath `<for>`, you can key only the first tag and that is enough to properly identify its sibilings as well
60>
61> ```marko
62> <dl>
63> <for|entry| of=entries>
64> <!-- only the first tag needs a key -->
65> <dt key=entry.id>${entry.word}</dt>
66> <!-- This key can be omitted -->
67> <dd>${entry.definition}</dd>
68> </for>
69> </dl>
70> ```
71
72> **Note:** If a key is not set, Marko will use the index of an item as its key. However this only works perfectly if items are only ever added or removed at the end of a list. Here's an example where things break down: if we have a list of `["A", "B", "C"]` and reverse the order, index keys would cause "A" to be transformed into "C" (and "C" into "A"), rather than just swapping them. Additionally if these components contained state, the new "C" would contain the state from the old "A" (and vice-versa). Be aware, stateful components include tags like the native `<input>` element. For this reason **it is always recommended to set a `key` on tags in a `<for>`.**