Skip to content

Commit 03fbaba

Browse files
authored
Merge pull request #18885 from NDCallahan/feat-enhance-update-field-value-to-allow-multiple-updates
feat: enhance Update Field Value action to support multiple fields
2 parents 9bb6f35 + 2c1f45e commit 03fbaba

2 files changed

Lines changed: 113 additions & 31 deletions

File tree

packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/UpdateFieldValue.svelte

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
<script>
2-
import { Select, Label, Combobox } from "@budibase/bbui"
2+
import { Select, Label, Multiselect } from "@budibase/bbui"
33
import { onMount } from "svelte"
44
import DrawerBindableInput from "@/components/common/bindings/DrawerBindableInput.svelte"
55
import { selectedScreen, componentStore } from "@/stores/builder"
66
import { getActionProviders, buildFormSchema } from "@/dataBinding"
77
import { findComponent } from "@/helpers/components"
88
9-
export let parameters
10-
export let bindings = []
11-
export let nested
9+
let { parameters, bindings = [], nested } = $props()
1210
1311
const typeOptions = [
1412
{
@@ -21,17 +19,18 @@
2119
},
2220
]
2321
24-
$: formComponent = getFormComponent(
25-
$selectedScreen.props,
26-
parameters.componentId
22+
const formComponent = $derived(
23+
getFormComponent($selectedScreen.props, parameters.componentId)
2724
)
28-
$: formSchema = buildFormSchema(formComponent)
29-
$: fieldOptions = Object.keys(formSchema || {})
30-
$: actionProviders = getActionProviders(
31-
$selectedScreen,
32-
$componentStore.selectedComponentId,
33-
"ValidateForm",
34-
{ includeSelf: nested }
25+
const formSchema = $derived(buildFormSchema(formComponent))
26+
const fieldOptions = $derived(Object.keys(formSchema || {}))
27+
const actionProviders = $derived(
28+
getActionProviders(
29+
$selectedScreen,
30+
$componentStore.selectedComponentId,
31+
"ValidateForm",
32+
{ includeSelf: nested }
33+
)
3534
)
3635
3736
const getFormComponent = (asset, id) => {
@@ -51,6 +50,22 @@
5150
parameters.type = "set"
5251
}
5352
})
53+
54+
const handleFieldChange = e => {
55+
// Convert from single field to multi-select format
56+
parameters.fields = e.detail || []
57+
// Initialize fieldValues for new fields
58+
if (!parameters.fieldValues) {
59+
parameters.fieldValues = {}
60+
}
61+
}
62+
63+
const handleFieldValueChange = (fieldName, value) => {
64+
if (!parameters.fieldValues) {
65+
parameters.fieldValues = {}
66+
}
67+
parameters.fieldValues[fieldName] = value
68+
}
5469
</script>
5570
5671
<div class="root">
@@ -67,16 +82,31 @@
6782
bind:value={parameters.type}
6883
options={typeOptions}
6984
/>
70-
<Label small>Field</Label>
71-
<Combobox bind:value={parameters.field} options={fieldOptions} />
72-
{#if parameters.type === "set"}
73-
<Label small>Value</Label>
74-
<DrawerBindableInput
75-
title="Field value"
76-
{bindings}
77-
value={parameters.value}
78-
on:change={e => (parameters.value = e.detail)}
79-
/>
85+
<Label small>Fields</Label>
86+
<Multiselect
87+
value={parameters.fields || []}
88+
on:change={handleFieldChange}
89+
options={fieldOptions}
90+
placeholder={parameters.type === "reset"
91+
? "Select fields to reset"
92+
: "Select fields to set"}
93+
/>
94+
{#if parameters.type === "set" && parameters.fields?.length > 0}
95+
<div class="field-values">
96+
{#each parameters.fields as fieldName}
97+
<div class="field-value-pair">
98+
<div class="label-col">{fieldName}</div>
99+
<div class="input-col">
100+
<DrawerBindableInput
101+
title="Value for {fieldName}"
102+
{bindings}
103+
value={parameters.fieldValues?.[fieldName]}
104+
on:change={e => handleFieldValueChange(fieldName, e.detail)}
105+
/>
106+
</div>
107+
</div>
108+
{/each}
109+
</div>
80110
{/if}
81111
</div>
82112
@@ -85,9 +115,43 @@
85115
display: grid;
86116
column-gap: var(--spacing-l);
87117
row-gap: var(--spacing-s);
88-
grid-template-columns: 60px 1fr;
118+
grid-template-columns: 90px 1fr;
89119
align-items: center;
90120
max-width: 400px;
91121
margin: 0 auto;
92122
}
123+
124+
.field-values {
125+
grid-column: 1 / -1;
126+
display: flex;
127+
flex-direction: column;
128+
gap: 0;
129+
overflow: hidden;
130+
border-top: 1px solid var(--spectrum-global-color-gray-200);
131+
border-bottom: 1px solid var(--spectrum-global-color-gray-200);
132+
}
133+
134+
.field-value-pair {
135+
display: grid;
136+
grid-template-columns: 130px 1fr;
137+
column-gap: var(--spacing-m);
138+
align-items: center;
139+
padding: var(--spacing-m) 0;
140+
border-bottom: 1px solid var(--spectrum-global-color-gray-200);
141+
}
142+
143+
.field-value-pair:last-child {
144+
border-bottom: none;
145+
}
146+
147+
.label-col {
148+
font-size: 13px;
149+
font-weight: 500;
150+
color: var(--spectrum-global-color-gray-700);
151+
padding: 0 var(--spacing-l);
152+
}
153+
154+
.input-col {
155+
padding: 0 var(--spacing-l) 0 0;
156+
}
93157
</style>

packages/client/src/components/app/forms/InnerForm.svelte

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -459,17 +459,35 @@
459459
460460
const handleUpdateFieldValue = ({
461461
type,
462+
fields,
463+
fieldValues,
464+
// Legacy single-field format - coerce for backwards compatibility
462465
field,
463466
value,
464467
}: {
465468
type: "set" | "reset"
466-
field: string
467-
value: any
469+
fields?: string[]
470+
fieldValues?: Record<string, any>
471+
field?: string
472+
value?: any
468473
}) => {
469-
if (type === "set") {
470-
formApi.setFieldValue(field, value)
471-
} else {
472-
formApi.resetField(field)
474+
// Coerce legacy single-field format into the new multi-field format
475+
const resolvedFields = fields ?? (field ? [field] : [])
476+
const resolvedFieldValues =
477+
fieldValues ?? (field !== undefined ? { [field]: value } : {})
478+
479+
if (type === "set" && Object.keys(resolvedFieldValues).length > 0) {
480+
Object.entries(resolvedFieldValues).forEach(([fieldName, fieldValue]) => {
481+
formApi.setFieldValue(fieldName, fieldValue)
482+
})
483+
} else if (
484+
type === "reset" &&
485+
Array.isArray(resolvedFields) &&
486+
resolvedFields.length > 0
487+
) {
488+
resolvedFields.forEach(fieldName => {
489+
formApi.resetField(fieldName)
490+
})
473491
}
474492
}
475493

0 commit comments

Comments
 (0)