--- title: "Data Binding" description: "" --- Scripting allows you to read, modify, and subscribe to changes in View Model properties, as well as create new View Model instances at runtime. For a conceptual overview of View Models and how they drive your graphic, see [View Models & Data Binding](/editor/data-binding/overview). ## View Models There are three ways that a script can gain access to a View Model and its properties: - Accessing View Models through [Context](#context) - Data binding a [View Model as an input](#view-models-as-inputs) - Data [binding view model properties to inputs](#binding-inputs) ### Context The `init` lifecycle function includes a `context` parameter that gives you access to your view models. This allows you to read values (strings, enums, lists, etc.), set values, fire triggers, listen for triggers, and subscribe to value changes. In addition to view models, [Context](/scripting/api-reference/interfaces/context) gives you access to named assets and update scheduling. ```lua {5, 8, 11, 12} type MyNode = {} function init(self: MyNode, context: Context): boolean -- Get the view model from the node's immediate context. local vmi = context:viewModel() -- Get the root view model local rootVmi = context:rootViewModel() -- Get the view model from the parent node. local parentDC = dc:parent() local parentVmi = dc:viewModel() end return function(): Node return { init = init, } end ``` ### View Models as Inputs You can create a [Script Input](/scripting/script-inputs) that can be bound to a view model. This allows you to read values (strings, enums, lists, etc.), set values, fire triggers, listen for triggers, and subscribe to value changes. ```lua {3,7,15} type MyNode = { -- This input expects a view model instance of type Character character: Input } function init(self: MyNode, context: Context): boolean local vmi = self.character end return function(): Node return { init = init, -- Initialize with `late()` so the value -- can be provided by the editor at runtime. character = late(), } end ``` For a detailed explanation, see [View Models Inputs](/scripting/script-inputs#view-model-inputs). ### Binding Inputs If you only need to read, not set view model properties, you can data bind view model property values to script inputs. For more information see [Data Binding Inputs](/scripting/script-inputs#data-binding-inputs). ### Nested View Models To reference a nested view model, use `getViewModel`. ```lua local vmi = context:viewModel(), local dateVmi = vmi:getViewModel('dateViewModel') ``` ## Reading and Setting Properties The following methods allow you to reference view model properties: - [getNumber](/scripting/api-reference/interfaces/view-model#getnumber) - [getTrigger](/scripting/api-reference/interfaces/view-model#gettrigger) - [getString](/scripting/api-reference/interfaces/view-model#getstring) - [getBoolean](/scripting/api-reference/interfaces/view-model#getboolean) - [getColor](/scripting/api-reference/interfaces/view-model#getcolor) - [getList](/scripting/api-reference/interfaces/view-model#getlist) - [getViewModel](/scripting/api-reference/interfaces/view-model#getviewmodel) - [getEnum](/scripting/api-reference/interfaces/view-model#getenum) ```lua {5,8,11,15,18} local vmi = context:viewModel() if vmi then -- Get a reference to the score property from the view model local score = vmi:getNumber('score') if score then -- Read the score print(score.value) -- Set the score score.value = 100 end -- Get a reference to the myTrigger property from the view model local myTrigger = vmi:getTrigger('myTrigger') if myTrigger then -- Fire the trigger mytrigger:fire() end end ``` ## Listening for Property Changes ### Add a Listener Use `addListener` to listen for triggers or changes to view model properties. ```lua {17,23} type MyNode = {} function handleHoursChanged() print('hours changed!') end function handleTriggerFired() print('Fire!') end function init(self: MyNode, context: Context): boolean local vmi = context:viewModel() local hours = vm:getNumber('hours') if hours then -- handleHoursChanged is called whenever the hours value changes hours:addListener(handleHoursChanged) end local trigger = vm:getTrigger('triggerProperty') if trigger then -- handleTriggerFired is called whenever the trigger is fired trigger:addListener(handleTriggerFired) end return true end return function(): Node return { init = init, } end ``` ### Remove a Listener Always remove listeners when they are no longer needed to avoid memory leaks. ```lua highlight={17} type MyNode = {} function init(self: MyNode, context: Context): boolean local vmi = context:viewModel() if not vmi then print('No view model found') return false end local hours = vmi:getNumber('hours') if hours then local function handleHoursChanged() print('hours changed!') -- Remove the event listener hours:removeListener(handleHoursChanged) end -- handleHoursChanged is called whenever the hours value changes hours:addListener(handleHoursChanged) end return true end return function(): Node return { init = init, hours = late(), trigger = late(), } end ``` ## Creating a View Model Instance Coming soon