Input
An input is not a layout named useInputLayout, but it is still a fundamental FormField shape.
The relevant API is createInput(...).
Signature
ts
import { createInput } from "@duplojs/form/vue";
const useMyInput = createInput(component, defaultParams);Then:
ts
const field = useMyInput(params);Parameters of createInput(...)
ts
createInput(component, {
defaultValue,
props?,
template?,
});component: Vue component compatible with the input contract.defaultValue: default value of the field. Required.props: default props injected into the component.template: defaultinputtemplate.
Parameters of useMyInput(...)
ts
useMyInput({
label?,
defaultValue?,
props?,
dataParser?,
class?,
template?,
});label: label forwarded to the template.defaultValue: local override of the initial value.props: local props passed to the component.dataParser: validation and transformation applied after the component.class: CSS class added to the template.template: local override of theinputtemplate.
Vue input component contract
The component must:
- accept
modelValue; - emit
update:modelValue; - accept an
idinjected by the library.
It can also expose:
ts
{
check?(): Either;
reset?(): void;
dispose?(): void;
}input template contract
Props
ts
{
getLabel?(): string;
getCurrentValue(): unknown;
getErrorMessage?(): string | null;
fieldKey: string;
}Slots
ts
{
input(): any;
}Small template example
vue
<script setup lang="ts">
import { type InputTemplateProperties } from "@duplojs/form/vue";
defineProps<InputTemplateProperties["props"]>();
defineSlots<InputTemplateProperties["slots"]>();
</script>
<template>
<div>
<label v-if="getLabel">
{{ getLabel() }}
</label>
<slot name="input" />
<small v-if="getErrorMessage">
{{ getErrorMessage() }}
</small>
</div>
</template>ts
import { createTemplate } from "@duplojs/form/vue";
import MyInputTemplate from "./inputTemplate.vue";
export const useMyInputTemplate = createTemplate(
"input",
MyInputTemplate,
);Minimal example
ts
import { createInput } from "@duplojs/form/vue";
import BasicTextInput from "./BasicTextInput.vue";
export const useBasicTextInput = createInput(
BasicTextInput,
{
defaultValue: "",
},
);Example with local validation
vue
<script setup lang="ts">
import * as EE from "@duplojs/utils/either";
import { type ExposeInputProperties } from "@duplojs/form/vue";
import { ref } from "vue";
export interface Props {
id: string;
label: string;
required?: boolean;
errorMessage?: string;
}
const props = withDefaults(
defineProps<Props>(),
{
required: false,
errorMessage: "You must accept this condition.",
},
);
const model = defineModel<boolean>({ default: false });
const currentError = ref<string | null>(null);
defineExpose<ExposeInputProperties>({
check: () => {
if (!props.required || model.value) {
currentError.value = null;
return EE.success(model.value);
}
currentError.value = props.errorMessage;
return EE.error([{ key: props.id }]);
},
reset: () => {
currentError.value = null;
},
});
</script>
<template>
<div>
<label>
<input
v-model="model"
type="checkbox"
:id="props.id"
/>
{{ props.label }}
</label>
<small v-if="currentError">
{{ currentError }}
</small>
</div>
</template>What to remember
- an input is already a
FormField; createInput(...)builds a field factory;- validation can happen in the component, in
dataParser, or in both.
