-
Notifications
You must be signed in to change notification settings - Fork 0
Data Binding
TesseraUI supports dynamic content through a TesseraModel object passed at render time. Templates can read model values with {{ }} expressions, loop with v-for, and show/hide elements with v-if and v-show.
Build a model from a flat key-value map:
TesseraModel model = TesseraModel.of(Map.of(
"player.name", player.getName().getString(),
"player.level", String.valueOf(playerLevel),
"player.health", String.valueOf((int) player.getHealth()),
"items.count", String.valueOf(items.size())
));All values are strings. Numeric comparisons in expressions work on the string representation.
Use TesseraModel.EMPTY when your template has no dynamic content.
Reference model values directly:
<label>Hello, {{ player.name }}!</label>
<label>Level: {{ player.level }}</label><label>{{ player.name }} — Level {{ player.level }}</label><label>{{ items.count == 0 ? "Empty" : items.count + " items" }}</label>Supported operators: ==, !=, >, <, >=, <=.
<label>{{ items.count == 0 ? t:ui.mymod.empty : items.count + " " + t:ui.mymod.items }}</label>Use : (with spaces) as the ternary separator when a t: key is involved.
Repeat a block for each item in a list.
Pass the count and per-item fields:
TesseraModel model = TesseraModel.of(Map.of(
"items", String.valueOf(items.size()), // count
"item.name.0", items.get(0).getName(),
"item.rarity.0", items.get(0).getRarity(),
"item.name.1", items.get(1).getName(),
"item.rarity.1", items.get(1).getRarity()
));<col v-for="item in items">
<label>{{ item.name }}</label>
<badge>{{ item.rarity }}</badge>
</col>item is the loop variable. Inside the template, {{ item.name }} resolves to item.name.<index> from the model.
<col v-for="slot in hotbar">
<label>{{ slot.name }}</label>
<label>× {{ slot.count }}</label>
</col>Completely removes the element and its layout space when the expression is falsy:
<row v-if="player.isAdmin">
<button onclick="openAdmin">Admin panel</button>
</row>The element is not rendered and takes no space in the layout when the condition is false.
<!-- Numeric comparison -->
<label v-if="items.count > 0">{{ items.count }} items available</label>
<!-- String equality -->
<badge v-if="player.rank == admin">Admin</badge>Keeps the element in the layout (space is preserved) but hides it:
<label v-show="player.isOnline">● Online</label>Use v-show when you want to avoid layout shifts on state changes. Use v-if when the element should never reserve space.
Bindings work in attributes too:
<img src="{{ player.avatarPath }}"/>
<item-slot item="{{ player.heldItem }}"/>
<input value="{{ config.defaultName }}"/>Map<String, String> data = new HashMap<>();
data.put("entries", String.valueOf(entries.size()));
for (int i = 0; i < entries.size(); i++) {
data.put("entry.name." + i, entries.get(i).getName());
data.put("entry.count." + i, String.valueOf(entries.get(i).getCount()));
}
TesseraModel model = TesseraModel.of(data);For dynamic resolution:
TesseraModel model = key -> {
if (key.equals("time")) return LocalTime.now().toString();
return null;
};