diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index f6e861137b..887695d41e 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -1,6 +1,10 @@ import { cloneDeep } from "lodash/fp" import { get } from "svelte/store" -import { findComponent, findComponentPath } from "./storeUtils" +import { + findComponent, + findComponentPath, + findAllMatchingComponents, +} from "./storeUtils" import { store } from "builderStore" import { tables as tablesStore, queries as queriesStores } from "stores/backend" import { makePropSafe } from "@budibase/string-templates" @@ -262,13 +266,12 @@ const getDeviceBindings = () => { * Gets all state bindings that are globally available. */ const getStateBindings = () => { - return [ - { - type: "context", - runtimeBinding: makePropSafe("state"), - readableBinding: `State`, - }, - ] + const safeState = makePropSafe("state") + return getAllStateVariables().map(key => ({ + type: "context", + runtimeBinding: `${safeState}.${makePropSafe(key)}`, + readableBinding: `State.${key}`, + })) } /** @@ -473,3 +476,49 @@ export function runtimeToReadableBinding(bindableProperties, textWithBindings) { "readableBinding" ) } + +/** + * Returns an array of the keys of any state variables which are set anywhere + * in the app. + */ +export const getAllStateVariables = () => { + let allComponents = [] + + // Find all onClick settings in all layouts + get(store).layouts.forEach(layout => { + const components = findAllMatchingComponents( + layout.props, + c => c.onClick != null + ) + allComponents = allComponents.concat(components || []) + }) + + // Find all onClick settings in all screens + get(store).screens.forEach(screen => { + const components = findAllMatchingComponents( + screen.props, + c => c.onClick != null + ) + allComponents = allComponents.concat(components || []) + }) + + // Add state bindings for all state actions + let bindingSet = new Set() + allComponents.forEach(component => { + if (!Array.isArray(component.onClick)) { + return + } + component.onClick.forEach(action => { + if ( + action["##eventHandlerType"] === "Update State" && + action.parameters?.type === "set" && + action.parameters?.key && + action.parameters?.value + ) { + bindingSet.add(action.parameters.key) + } + }) + }) + + return Array.from(bindingSet) +} diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/UpdateState.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/UpdateState.svelte index c85ad70289..c9a0c2119e 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/UpdateState.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/UpdateState.svelte @@ -1,11 +1,13 @@