Skip to content

Latest commit

 

History

History
147 lines (118 loc) · 5.1 KB

4. repeat-ui.md

File metadata and controls

147 lines (118 loc) · 5.1 KB

Repeat UI

Introduction

There are cases when you need to build up UI that repeats a defined structure. Given an array you need to create a new instance of the template element and bind it to the item.

<div>
    <template for="contact of person.contacts" data-reference="contact">
        <label>
            <div>Cell Number</div>
            <input value.bind="contact.cell">
        </label>
    </template>
</div>

person is a property on the binding context. The person object has an array property called contacts. For each object in the array the structure.
Note the data-reference attribute on the template.
This is a optional attribute that you can use for debugging the data structure.
For each list item a context is created in the binding data and the name of that context is normally "array-item".
If you want provide a different contextual name for the item, you can do so by setting a data-reference attribute to the name you want uses.

<label>
    <div>Cell Number</div>
    <input value.bind="contact.cell">
</label>

will be added to the div parent element.

The syntax here borrows from the JavaScript for syntax. You have to provide a context in for the item in the array. In the above example it is "contact". When defining binding expressions you need to base it on the context name you provided. You can see an example of this on the input binding "contact.cell"

One thing that is not wise to do is to define events on each item. That is bad practice even with out binding. Rather define your events on the parent element and use the target property on the event to find out what child was interacted on.

For static implementations you can use for.once instead of just for.
The syntax looks the sake but the result is much different.
for.once uses the inflation manager and generates static UI.
Once this UI is introduced to the dom it will not change again even if the data does change.
The upside to this is that it uses much less overhead because it does not have to listen to changes.

The standard for will respond to data changes in the array objects and update bindings and also to array structure changes.
The cost you pay for this is the listener and update overhead required to make this work.

If you do not expect changes, for example you are generating a list of options for a select, rather use for.once.

<template for.once="item of items">
    <div>${item.title}</div>
</template>

Sometimes you are dealing with an array of values.
In those cases you can use the defined context name directly.

<template for.once="item of items">
    <div data-title="{item}">${item}</div>
</template>

NOTE: for.once creates the UI and does not monitor it after the fact.
Because of this, you can bind using an array of values.

for interacts with the UI after the initial create process.
Because of this, markers are placed on objects used in the for operation.
This means that you must use an object when using for NOT just values.

Maps

You can bind to map objects in the same way

<template for.map="item of data">
    <div data-key="${item.key}">${item.value.title}</div>
</template>

The one difference is that the item object will have two properties.

  1. key
  2. value

Radio groups

Radio groups can be iffy to work with, so we added a provider to make it easier.
This expression uses for.radio on a template with an additional property attribute.
Please note that this operates much the same way as an for.once, once the list is printed that is it.
The data should also be populated during the preLoad function to ensure it is there by the time the elements are being processed.

The property attribute is the property relative to the binding context that will be set with the selected radio's value attribute.

<div style="display: flex; flex-direction: column" id="people">
    <template for.radio="person of people" property="selectedPerson">
        <label>
            <input value="${person.value}" />
            <span>${person.title}</span>
        </label>
    </template>
</div>

Consider the above example:

  1. Ensure this is done inside of a parent element that acts as a container for that group.
  2. You must provide the for.radio and property attributes on the template.
  3. You don't need to provide the type or name attributes, that is filled in for you.
  4. The name attribute will be set to the collection path you define in the for.radio expression.

When creating the elements, if the value of the input matches the value of the value in the property you defined on the template that input will be marked as checked.

As you move the mouse, the div's content will show the mouses x and y positions. No additional code required.
So if this is my data:

this.setProperty("people", [
    {
        id: 1,
        title: "John",
        value: 1
    },
    {
        id: 2,
        title: "Samantha",
        value: 2,
    },
    {
        id: 3,
        title: "Rodger",
        value: 3
    },
    {
        id: 4,
        title: "Mike",
        value: 4
    }
])

this.setProperty("selectedPerson", 2);