State Management in Basalt
States provide a new way to manage data and UI synchronization in your Basalt applications.
Detailed State Methods
initializeState
lua
BaseFrame:initializeState("name", defaultValue, persistent, path?)
BaseFrame:initializeState("name", defaultValue, persistent, path?)
Creates a new state in a BaseFrame:
name
: Name of the state (string)defaultValue
: Initial value of the state (any type)persistent?
: Boolean that determines if the state should be stored into a filepath?
: The path the state should be stored to (default: states/BaseFrameNAME.state)- Returns: self (for method chaining)
setState
lua
element:setState("name", newValue)
element:setState("name", newValue)
Updates an existing state's value:
name
: Name of the state to updatenewValue
: New value to set- Automatically triggers UI updates if triggerRender=true
- Returns: self (for method chaining)
getState
lua
local value = element:getState("name")
local value = element:getState("name")
Retrieves the current value of a state:
name
: Name of the state to get- Returns: Current value of the state
computed
lua
element:computed("name", function(self)
local otherState = self:getState("otherState")
return someCalculation(otherState)
end)
element:computed("name", function(self)
local otherState = self:getState("otherState")
return someCalculation(otherState)
end)
Creates a computed state that depends on other states:
name
: Name of the computed statefunction
: Function that calculates the value- Automatically recalculates when dependent states change
- Returns: self (for method chaining)
onStateChange
lua
element:onStateChange("name", function(self, newValue)
-- React to changes
self:someAction(newValue)
end)
element:onStateChange("name", function(self, newValue)
-- React to changes
self:someAction(newValue)
end)
Registers a listener for state changes:
name
: Name of the state to watchfunction
: Callback function receiving the new value- Executes whenever the state changes
- Returns: self (for method chaining)
bind
lua
local name = form:addInput():bind("text", "name")
local name = form:addInput():bind("text", "name")
Binds a property to a state
propertyName
: The name of the propertystateName
: The name of the state- Returns: self (for method chaining)
Example: Form Validation
Here's a comprehensive example showing state management in a form:
lua
local main = basalt.getMainFrame()
-- Initialize form states
:initializeState("username", "", true) -- make them persistent
:initializeState("password", "", true) -- make them persistent
:initializeState("confirmPassword", "", true) -- make them persistent
local form = main:addFrame()
:setSize("{parent.width - 4}", "{parent.height - 4}")
:setPosition(3, 3)
-- Add computed validation state
form:computed("isValid", function(self)
local username = self:getState("username")
local password = self:getState("password")
local confirmPass = self:getState("confirmPassword")
return #username >= 3 and #password >= 6 and password == confirmPass
end)
-- Create labels
form:addLabel({text="Username:", x = 2, y = 2, foreground = colors.lightGray})
form:addLabel({text="Password:", x = 2, y = 4, foreground = colors.lightGray})
form:addLabel({text="Confirm:", x = 2, y = 6, foreground = colors.lightGray})
local userInput = form:addInput({x = 11, y = 2, width = 20, height = 1}):bind("text", "username")
local passwordInput = form:addInput({x = 11, y = 4, width = 20, height = 1}):bind("text", "password")
local confirmInput = form:addInput({x = 11, y = 6, width = 20, height = 1}):bind("text", "confirmPassword")
-- Submit button
local submitBtn = form:addButton()
:setText("Submit")
:setPosition(2, 8)
:setSize(29, 1)
-- Status label
local statusLabel = form:addLabel()
:setPosition(2, 10)
:setSize(29, 1)
form:onStateChange("isValid", function(self, isValid)
if isValid then
statusLabel:setText("Form is valid!")
:setForeground(colors.green)
submitBtn:setBackground(colors.green)
else
statusLabel:setText("Please fill all fields correctly")
:setForeground(colors.red)
submitBtn:setBackground(colors.red)
end
end)
local main = basalt.getMainFrame()
-- Initialize form states
:initializeState("username", "", true) -- make them persistent
:initializeState("password", "", true) -- make them persistent
:initializeState("confirmPassword", "", true) -- make them persistent
local form = main:addFrame()
:setSize("{parent.width - 4}", "{parent.height - 4}")
:setPosition(3, 3)
-- Add computed validation state
form:computed("isValid", function(self)
local username = self:getState("username")
local password = self:getState("password")
local confirmPass = self:getState("confirmPassword")
return #username >= 3 and #password >= 6 and password == confirmPass
end)
-- Create labels
form:addLabel({text="Username:", x = 2, y = 2, foreground = colors.lightGray})
form:addLabel({text="Password:", x = 2, y = 4, foreground = colors.lightGray})
form:addLabel({text="Confirm:", x = 2, y = 6, foreground = colors.lightGray})
local userInput = form:addInput({x = 11, y = 2, width = 20, height = 1}):bind("text", "username")
local passwordInput = form:addInput({x = 11, y = 4, width = 20, height = 1}):bind("text", "password")
local confirmInput = form:addInput({x = 11, y = 6, width = 20, height = 1}):bind("text", "confirmPassword")
-- Submit button
local submitBtn = form:addButton()
:setText("Submit")
:setPosition(2, 8)
:setSize(29, 1)
-- Status label
local statusLabel = form:addLabel()
:setPosition(2, 10)
:setSize(29, 1)
form:onStateChange("isValid", function(self, isValid)
if isValid then
statusLabel:setText("Form is valid!")
:setForeground(colors.green)
submitBtn:setBackground(colors.green)
else
statusLabel:setText("Please fill all fields correctly")
:setForeground(colors.red)
submitBtn:setBackground(colors.red)
end
end)
Tips
State Initialization
- Always initialize states at component creation
- Use descriptive state names
- Consider carefully whether updates should trigger renders
Computed States
- Use for values derived from other states
- Keep calculations simple and performant
- Avoid circular dependencies
State Updates
- Only modify states through setState
- Use onStateChange for side effects
- Batch multiple updates when possible
Common Patterns
- Form validation
- UI state management
- Data synchronization
- Component communication