diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index c236dd1ad9..7da7c60abe 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -7206,7 +7206,8 @@
{
"type": "table",
"label": "Data",
- "key": "dataSource"
+ "key": "dataSource",
+ "validator": "checkValidDatasource"
},
{
"type": "radio",
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 79b4ca6f68..4926965e45 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -40,6 +40,7 @@
getActionDependentContextKeys,
} from "../utils/buttonActions.js"
import { gridLayout } from "utils/grid"
+ import { validateComponentSetting } from "utils/componentsValidator"
export let instance = {}
export let parent = null
@@ -103,6 +104,7 @@
let settingsDefinition
let settingsDefinitionMap
let missingRequiredSettings = false
+ let invalidSettings = false
// Temporary styles which can be added in the app preview for things like
// DND. We clear these whenever a new instance is received.
@@ -141,12 +143,16 @@
$: showEmptyState = definition?.showEmptyState !== false
$: hasMissingRequiredSettings = missingRequiredSettings?.length > 0
$: editable = !!definition?.editable && !hasMissingRequiredSettings
+ $: hasInvalidSettings = invalidSettings?.length > 0
$: requiredAncestors = definition?.requiredAncestors || []
$: missingRequiredAncestors = requiredAncestors.filter(
ancestor => !$component.ancestors.includes(`${BudibasePrefix}${ancestor}`)
)
$: hasMissingRequiredAncestors = missingRequiredAncestors?.length > 0
- $: errorState = hasMissingRequiredSettings || hasMissingRequiredAncestors
+ $: errorState =
+ hasMissingRequiredSettings ||
+ hasMissingRequiredAncestors ||
+ hasInvalidSettings
// Interactive components can be selected, dragged and highlighted inside
// the builder preview
@@ -338,6 +344,21 @@
return missing
})
+ // Check for invalid settings
+ invalidSettings = settingsDefinition.reduce((invalidSettings, setting) => {
+ if (setting.validator) {
+ const error = validateComponentSetting(
+ setting.validator,
+ instance[setting.key]
+ )
+ if (error) {
+ invalidSettings.push(error)
+ }
+ }
+
+ return invalidSettings
+ }, [])
+
// When considering bindings we can ignore children, so we remove that
// before storing the reference stringified version
const noChildren = JSON.stringify({ ...instance, _children: null })
@@ -692,6 +713,7 @@
{:else}
diff --git a/packages/client/src/components/error-states/ComponentErrorState.svelte b/packages/client/src/components/error-states/ComponentErrorState.svelte
index b846eaa230..ba55e3cdc1 100644
--- a/packages/client/src/components/error-states/ComponentErrorState.svelte
+++ b/packages/client/src/components/error-states/ComponentErrorState.svelte
@@ -9,6 +9,7 @@
| { key: string; label: string }[]
| undefined
export let missingRequiredAncestors: string[] | undefined
+ export let invalidSettings: string[] | undefined
const component = getContext("component")
const { styleable, builderStore } = getContext("sdk")
@@ -16,6 +17,7 @@
$: styles = { ...$component.styles, normal: {}, custom: null, empty: true }
$: requiredSetting = missingRequiredSettings?.[0]
$: requiredAncestor = missingRequiredAncestors?.[0]
+ $: invalidSetting = invalidSettings?.[0]
{#if $builderStore.inBuilder}
@@ -24,6 +26,8 @@
{#if requiredAncestor}
+ {:else if invalidSetting}
+ {invalidSetting}
{:else if requiredSetting}
{/if}
diff --git a/packages/client/src/utils/componentsValidator.ts b/packages/client/src/utils/componentsValidator.ts
new file mode 100644
index 0000000000..6609f92ed6
--- /dev/null
+++ b/packages/client/src/utils/componentsValidator.ts
@@ -0,0 +1,13 @@
+const validators = {
+ checkValidDatasource: (a: any) => {
+ return `Ups... "${a.label}" not found`
+ },
+}
+
+export function validateComponentSetting(
+ key: keyof typeof validators,
+ value: any
+) {
+ const validator = validators[key]
+ return validator(value)
+}