This commit is contained in:
Aaron Smith 2023-09-14 18:15:54 +01:00
parent bdd725659e
commit d77fe0f92f
34 changed files with 1215 additions and 566 deletions

View file

@ -1,66 +1,95 @@
# Control Flow
Vide has specific functions for dealing with sources that store a table value.
Eventually you will need a way to dynamically create and destroy UI elements
resulting from state changes. Vide provides functions to help you do this,
known as *control flow* functions.
These functions return a new source, which holds the instances to be displayed.
These sources can be assigned as children, meaning the displayed children
will update when the input source updates.
One of these functions is `switch()`, used to conditionally show one of a set of
components.
```lua
local vide = require(vide)
local source = vide.source
local switch = vide.switch
local function ToggleButton(p: {
Text: string,
Toggle: (boolean) -> boolean
})
return create "TextButton" {
Size = UDim2.fromOffset(300, 300),
Text = p.Text,
Activated = function()
p.Toggle(not p.Toggle())
end
}
end
local loggedIn = source(false)
local function LoginMenu()
return Frame {
switch(loggedIn) {
[true] = function()
return ToggleButton { Text = "Log out", Toggle = loggedIn }
end,
[false] = function()
return ToggleButton { Text = "Log in", Toggle = loggedIn }
end
}
}
end
mount(function() return create "ScreenGui" { LoginMenu {} } end, game.StarterGui)
```
Above is an example of using a switch to create a login menu. Each time
`loggedIn` toggles, the current button will be destroyed, and a new button
created, which the text to represent the current action, to log in or log out.
Another control flow function, `indexes()`, is used to create elements from an
input table.
Often, you will have a table of values that will be displayed in a similar
manner. Rather than manually looping over each value to generate a corresponding
UI element, Vide provides functions `indexes()` and `values()` to do this for
you.
`indexes()` maps each *index* in a table to a UI element.
UI element, `indexes()` can autmatically run a transform function for each
index and value, generating a UI element.
```lua
local names = source { "a", "b", "c" }
local todoList = {
"Finish the crash course",
"Star vide's GitHub"
}
local elements = indexes(names, function(name, i)
local elements = indexes(todoList, function(todo, i)
return create "TextLabel" {
Text = function()
return "Name: " .. name()
return i .. ": " .. todo()
end,
LayoutOrder = i
}
end)
```
What happens here is the given callback is only ever ran *once* for each index
in the table. The callback receives two arguments, a *source* containing the
index's value and then the index itself.
Anytime the value at a corresponding index changes, the source for that index
value is updated, causing the UI element depending on it to update too.
`values()` behaves similarly, except it maps each *value* in a table to a UI
element.
```lua
type Item = {
Name: string,
Icon: number
}
local items = source({} :: Array<Item>)
local elements = values(items, function(item, i)
return create "ImageLabel" {
Image = "rbxassetid://" .. item.Icon,
LayoutOrder = i
mount(function()
return create "ScreenGui" {
create "UIListLayout" {}, elements
}
end)
end, game.StarterGui)
```
The callback is again only ever ran *once* for each value in the table. The
callback receives two arguments, a value in the table and then a *source*
containing the value's corresponding index.
For each unique index in the passed table, the transform function will be called
with 1. a source containing the value of the index, 2. the index itself.
Any time a value in a table changes index, the source for that value is updated,
causing the UI element position to change.
When the value at an index is changed, the function is not reran. Instead, the
given source is updated instead.
In certain cases `values()` can cause less recalculation and rerenders than
`indexes()` like when items are re-arranged and shifted within a table.
`indexes()` is said to map each *index* in a table to a UI element, each index
has a single corresponding element.
It is important that each value in a table is unique when using `values()`,
and for this reason always using `indexes()` if a table contains primitive
values.
Both `indexes()` and `values()` return an array of all mapped UI elements.
An element is only destroyed if the value of an index is set to `nil`.