Mutate state when working with form steps to prevent latency issues

This commit is contained in:
Andrew Kingston 2023-12-13 10:24:26 +00:00
parent 1579fe36c7
commit 235cfa3660
2 changed files with 91 additions and 79 deletions

View File

@ -97,7 +97,8 @@
} }
const addStep = () => { const addStep = () => {
dispatch("change", value.toSpliced($currentStep + 1, 0, {})) value = value.toSpliced($currentStep + 1, 0, {})
dispatch("change", value)
multiStepStore.update(state => ({ multiStepStore.update(state => ({
...state, ...state,
currentStep: $currentStep + 1, currentStep: $currentStep + 1,
@ -105,7 +106,8 @@
} }
const removeStep = () => { const removeStep = () => {
dispatch("change", value.toSpliced($currentStep, 1)) value = value.toSpliced($currentStep, 1)
dispatch("change", value)
multiStepStore.update(state => ({ multiStepStore.update(state => ({
...state, ...state,
currentStep: Math.min($currentStep, stepCount - 2), currentStep: Math.min($currentStep, stepCount - 2),
@ -131,7 +133,8 @@
...value[$currentStep], ...value[$currentStep],
[field.key]: val, [field.key]: val,
} }
dispatch("change", value.toSpliced($currentStep, 1, newStep)) value = value.toSpliced($currentStep, 1, newStep)
dispatch("change", value)
} }
const handleStepAction = action => { const handleStepAction = action => {

View File

@ -5,7 +5,6 @@
import { builderStore } from "stores" import { builderStore } from "stores"
import { Utils } from "@budibase/frontend-core" import { Utils } from "@budibase/frontend-core"
export let componentInstance
export let steps export let steps
export let dataSource export let dataSource
export let initialFormStep = 1 export let initialFormStep = 1
@ -33,30 +32,42 @@
$: fetchSchema(dataSource) $: fetchSchema(dataSource)
$: enrichedSteps = enrichSteps(steps, schema, $component.id) $: enrichedSteps = enrichSteps(steps, schema, $component.id)
$: currentStep = getCurrentStep($builderStore, $component) $: currentStep = getCurrentStep(enrichedSteps, $builderStore, $component)
const getCurrentStep = (builderStore, component) => { const getCurrentStep = (steps, builderStore, component) => {
const { componentId, step } = builderStore.metadata || {}
// If we aren't in the builder or aren't selected then don't return a form
// step at all. This will let the form component take over state for which
// step is active.
if ( if (
!component.selected || !component.selected ||
!builderStore.inBuilder || !builderStore.inBuilder ||
builderStore.metadata?.componentId !== component.id componentId !== component.id
) { ) {
return null return null
} }
return (builderStore.metadata.step || 0) + 1
// Ensure we have a valid step selected
let currentStep = Math.min(step || 0, steps.length - 1)
// Sanity check
currentStep = Math.max(currentStep, 0)
// Add 1 because the form component expects 1 indexed rather than 0 indexed
return currentStep + 1
} }
const getPropsForField = field => { const getPropsForField = field => {
return field._component if (field._component) {
? { return field
...field, }
} return {
: { field: field.name,
field: field.name, label: field.name,
label: field.name, placeholder: field.name,
placeholder: field.name, _instanceName: field.name,
_instanceName: field.name, }
}
} }
const getComponentForField = field => { const getComponentForField = field => {
@ -102,69 +113,67 @@
} }
</script> </script>
{#key enrichedSteps} <Block>
<Block> <BlockComponent
<BlockComponent type="form"
type="form" props={{
props={{ dataSource,
dataSource, initialFormStep,
initialFormStep, step: currentStep,
step: currentStep, }}
}} context="form"
context="form" >
> {#each enrichedSteps as step, idx}
{#each enrichedSteps as step, idx} <BlockComponent
type="formstep"
props={{ step: idx + 1, _instanceName: `Step ${idx + 1}` }}
styles={{
normal: {
width: "600px",
"margin-left": "auto",
"margin-right": "auto",
},
}}
>
<BlockComponent <BlockComponent
type="formstep" type="container"
props={{ step: idx + 1, _instanceName: `Step ${idx + 1}` }} props={{
styles={{ gap: "M",
normal: { direction: "column",
width: "600px", hAlign: "stretch",
"margin-left": "auto", vAlign: "top",
"margin-right": "auto", size: "shrink",
},
}} }}
> >
<BlockComponent <BlockComponent type="container" order={0}>
type="container" <BlockComponent type="heading" props={{ text: step.title }} />
props={{
gap: "M",
direction: "column",
hAlign: "stretch",
vAlign: "top",
size: "shrink",
}}
>
<BlockComponent type="container" order={0}>
<BlockComponent type="heading" props={{ text: step.title }} />
</BlockComponent>
<BlockComponent type="text" props={{ text: step.desc }} order={1} />
<BlockComponent type="fieldgroup" order={2}>
{#each step.fields as field, fieldIdx}
{#if getComponentForField(field)}
<BlockComponent
type={getComponentForField(field)}
props={getPropsForField(field)}
order={fieldIdx}
interactive
name={field.field}
/>
{/if}
{/each}
</BlockComponent>
<BlockComponent
type="buttongroup"
props={{ buttons: step.buttons }}
styles={{
normal: {
"margin-top": "16px",
},
}}
order={3}
/>
</BlockComponent> </BlockComponent>
<BlockComponent type="text" props={{ text: step.desc }} order={1} />
<BlockComponent type="fieldgroup" order={2}>
{#each step.fields as field, fieldIdx}
{#if getComponentForField(field)}
<BlockComponent
type={getComponentForField(field)}
props={getPropsForField(field)}
order={fieldIdx}
interactive
name={field.field}
/>
{/if}
{/each}
</BlockComponent>
<BlockComponent
type="buttongroup"
props={{ buttons: step.buttons }}
styles={{
normal: {
"margin-top": "16px",
},
}}
order={3}
/>
</BlockComponent> </BlockComponent>
{/each} </BlockComponent>
</BlockComponent> {/each}
</Block> </BlockComponent>
{/key} </Block>