Skip to content

useStepLayout

useStepLayout(...) splits a form into successive steps.

Signature

ts
ts
useStepLayout(
	[
		stepA,
		stepB,
		stepC,
	],
	{
		errorMessageNotAtLastStep: string,
		class?: string,
		template?: Templates["step"],
	},
);

Parameters

  • formFields: tuple of FormField instances, one per step.
  • errorMessageNotAtLastStep: message displayed when check() is called before the last step.
  • class: CSS class added to the step template.
  • template: local override of the step template.

Produced value

Current value

ts
ts
{
	currentStep: number;
	steps: unknown[];
}

Validated value

ts
ts
unknown[]

If an error is detected during check(), the layout automatically resets currentStep to the first failing step.

step template contract

Props

ts
ts
{
	fieldKey: string;
	stepQuantity: number;
	isLastStep(): boolean;
	getFormFields(): (() => VNode)[];
	getCurrentValue(): unknown;
	getCurrentStep(): number;
	getErrorMessageNotAtLastStep(): null | string;
}

Emits

ts
ts
{
	nextStep: [];
	previousStep: [];
	resetStep: [];
}

Slots

ts
ts
{
	formField(): any;
}

Small template example

vue
vue
<script setup lang="ts">
import { type StepTemplateProperties } from "@duplojs/form/vue";

type Props = (
	& StepTemplateProperties["props"]
	& {
		nextLabel?: string;
		previousLabel?: string;
		resetLabel?: string;
	}
);

defineProps<Props>();
defineSlots<StepTemplateProperties["slots"]>();
defineEmits<StepTemplateProperties["emits"]>();
</script>

<template>
	<div>
		<slot name="formField" />

		<div>
			<button type="button" @click="$emit('previousStep')">
				Back
			</button>

			<button type="button" @click="$emit('resetStep')">
				Reset step
			</button>

			<button type="button" @click="$emit('nextStep')">
				Next
			</button>
		</div>
	</div>
</template>
ts
ts
import { createTemplate } from "@duplojs/form/vue";
import MyStepTemplate from "./stepTemplate.vue";

export const useMyStepTemplate = createTemplate(
	"step",
	MyStepTemplate,
	{
		props: {
			nextLabel: "Next",
			previousLabel: "Back",
		},
	},
);

Example

ts
ts
import { useMultiLayout, useStepLayout } from "@duplojs/form/vue";
import { useTextInput } from "@duplojs/form/vueDesignSystem";

export const onboarding = useStepLayout(
	[
		useMultiLayout({
			fullName: useTextInput({ label: "Full name" }),
		}),
		useMultiLayout({
			email: useTextInput({ label: "Email" }),
		}),
	],
	{
		errorMessageNotAtLastStep: "Complete all steps before submitting.",
	},
);

Use cases

  • onboarding;
  • signup funnel;
  • long forms with sequential progression.

Released under the MIT License.