useFieldArray
useFieldArray() is a custom Vue composition api that will return specific fields values, meta (state), attributes and provides common operation helpers, you can also add validation for those fields.
Usage
<script setup lang="ts">
import { useForm, useFieldArray } from '@vorms/core'
const { handleSubmit } = useForm({
initialValues: {
foods: ['Bubble Tea', 'Stinky Tofu', 'Scallion Pancake']
},
onSubmit(data) {
console.log(data)
}
})
const { fields, append } = useFieldArray<string>('foods')
</script>
<template>
<form @submit="handleSubmit">
<div v-for="field in fields" :key="field.key">
<input
v-model="field.value"
type="text"
:name="field.name"
v-bind="field.attrs"
>
</div>
<button type="button" @click="append('Taiwanese Fried Chicken')">
Append
</button>
<button type="submit">Order</button>
</form>
</template>
<script setup lang="ts">
import { useForm, useFieldArray } from '@vorms/core'
const { handleSubmit } = useForm({
initialValues: {
foods: ['Bubble Tea', 'Stinky Tofu', 'Scallion Pancake']
},
onSubmit(data) {
console.log(data)
}
})
const { fields, append } = useFieldArray<string>('foods')
</script>
<template>
<form @submit="handleSubmit">
<div v-for="field in fields" :key="field.key">
<input
v-model="field.value"
type="text"
:name="field.name"
v-bind="field.attrs"
>
</div>
<button type="button" @click="append('Taiwanese Fried Chicken')">
Append
</button>
<button type="submit">Order</button>
</form>
</template>
Params
name (Required)
Name of the field array.
- Type
MaybeRef<string>
options
- Type
interface UseFieldArrayOptions<Value> {
// This function allows you to write your logic to validate your field,
// this is optional.
validate?: FieldArrayValidator<Value[]>;
}
type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>;
interface UseFieldArrayOptions<Value> {
// This function allows you to write your logic to validate your field,
// this is optional.
validate?: FieldArrayValidator<Value[]>;
}
type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>;
The validate is a field level validation. This property accepts the field array's value as an argument. You can return an array or an undefined to determine whether or not this filed array is a valid value.
Returns
fields
This array contains every entry of field's key, value, meta and attrs.
Type
Ref<FieldEntry<Value>[]>tsinterface FieldEntry<Value> { key: number; value: Value; name: string; error: FormErrors<Value>; touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined; dirty: boolean; attrs: Omit<FieldAttrs, 'name'>; }interface FieldEntry<Value> { key: number; value: Value; name: string; error: FormErrors<Value>; touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined; dirty: boolean; attrs: Omit<FieldAttrs, 'name'>; }
useFieldArray automatically generates a unique identifier named key which is used for key prop. For more information why this is required: Maintaining State with key
The field.key must be added as the component key to prevent re-renders breaking the fields.
<template>
<!-- correct -->
<input v-for="field in fields" :key="field.key" />
<!-- incorrect -->
<input v-for="(field, index) in fields" :key="index" />
</template>
<template>
<!-- correct -->
<input v-for="field in fields" :key="field.key" />
<!-- incorrect -->
<input v-for="(field, index) in fields" :key="index" />
</template>
append
Append an item to the field array.
- Type
(value: Value) => void;
const { fields, append } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea']
append('Stinky Tofu')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea', 'Stinky Tofu']
const { fields, append } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea']
append('Stinky Tofu')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea', 'Stinky Tofu']
prepend
Prepend an item to the field array.
- Type
(value: Value) => void;
const { fields, prepend } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea']
prepend('Fried Chicken')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
const { fields, prepend } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea']
prepend('Fried Chicken')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
swap
Swap items position.
- Type
(indexA: number, indexB: number) => void
const { fields, swap } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Aiyu Jelly', 'Shaved Ice', 'Bubble Tea']
swap(0, 2)
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea', 'Shaved Ice', 'Aiyu Jelly']
const { fields, swap } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Aiyu Jelly', 'Shaved Ice', 'Bubble Tea']
swap(0, 2)
console.log(fields.value.map(field => field.value))
// output: ['Bubble Tea', 'Shaved Ice', 'Aiyu Jelly']
remove
Remove item at the specified position, or remove all when no index provided.
- Type
(index?: number) => void
const { fields, remove } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Century Egg', 'Stinky Tofu', 'Oyster Vermicelli Noodles']
remove(2)
console.log(fields.value.map(field => field.value))
// output: ['Century Egg', 'Stinky Tofu']
remove()
console.log(fields.value.map(field => field.value))
// output: []
const { fields, remove } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Century Egg', 'Stinky Tofu', 'Oyster Vermicelli Noodles']
remove(2)
console.log(fields.value.map(field => field.value))
// output: ['Century Egg', 'Stinky Tofu']
remove()
console.log(fields.value.map(field => field.value))
// output: []
move
Move item to another position.
- Type
(from: number, to: number) => void
const { fields, move } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Avocado', 'Shaved Ice', 'Bubble Tea']
move(0, 2)
console.log(fields.value.map(field => field.value))
// output: ['Shaved Ice', 'Bubble Tea', 'Avocado']
const { fields, move } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Avocado', 'Shaved Ice', 'Bubble Tea']
move(0, 2)
console.log(fields.value.map(field => field.value))
// output: ['Shaved Ice', 'Bubble Tea', 'Avocado']
insert
Insert item at the specified position.
- Type
(index: number, value: Value) => void
const { fields, insert } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Chicken Chop', 'Bubble Tea']
insert(1, 'Bubble Tea')
console.log(fields.value.map(field => field.value))
// output: ['Chicken Chop', 'Bubble Tea', 'Bubble Tea']
const { fields, insert } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Chicken Chop', 'Bubble Tea']
insert(1, 'Bubble Tea')
console.log(fields.value.map(field => field.value))
// output: ['Chicken Chop', 'Bubble Tea', 'Bubble Tea']
update
Update int at the specified position.
- Type
(index: number, value: Value) => void
const { fields, update } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
insert(0, 'Soup Dumplings')
console.log(fields.value.map(field => field.value))
// output: ['Soup Dumplings', 'Bubble Tea']
const { fields, update } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
insert(0, 'Soup Dumplings')
console.log(fields.value.map(field => field.value))
// output: ['Soup Dumplings', 'Bubble Tea']
replace
Replace the entire field array values.
- Type
(values: Value[]) => void
const { fields, update } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
insert(['Soup Dumplings', 'Three-Cup Chicken'])
console.log(fields.value.map(field => field.value))
// output: ['Soup Dumplings', 'Three-Cup Chicken']
const { fields, update } = useFieldArray('food')
console.log(fields.value.map(field => field.value))
// output: ['Fried Chicken', 'Bubble Tea']
insert(['Soup Dumplings', 'Three-Cup Chicken'])
console.log(fields.value.map(field => field.value))
// output: ['Soup Dumplings', 'Three-Cup Chicken']
Type Declarations
Show Type Declarations
function useFieldArray <Value>(name: MaybeRef<string>, options?: UseFieldArrayOptions<Value>): UseFieldArrayReturn<Value>
interface UseFieldArrayOptions<Value> {
validate?: FieldArrayValidator<Value[]>;
}
type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>;
type UseFieldArrayReturn<Value> = {
fields: Ref<FieldEntry<Value>[]>;
append: (value: Value) => void;
prepend: (value: Value) => void;
swap: (indexA: number, indexB: number) => void;
remove: (index?: number) => void;
move: (from: number, to: number) => void;
insert: (index: number, value: Value) => void;
update: (index: number, value: Value) => void;
replace: (values: Value[]) => void;
};
interface FieldEntry<Value> {
key: number;
value: Value;
name: string;
error: FormErrors<Value>;
touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined;
dirty: boolean;
attrs: Omit<FieldAttrs, 'name'>;
}
function useFieldArray <Value>(name: MaybeRef<string>, options?: UseFieldArrayOptions<Value>): UseFieldArrayReturn<Value>
interface UseFieldArrayOptions<Value> {
validate?: FieldArrayValidator<Value[]>;
}
type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>;
type UseFieldArrayReturn<Value> = {
fields: Ref<FieldEntry<Value>[]>;
append: (value: Value) => void;
prepend: (value: Value) => void;
swap: (indexA: number, indexB: number) => void;
remove: (index?: number) => void;
move: (from: number, to: number) => void;
insert: (index: number, value: Value) => void;
update: (index: number, value: Value) => void;
replace: (values: Value[]) => void;
};
interface FieldEntry<Value> {
key: number;
value: Value;
name: string;
error: FormErrors<Value>;
touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined;
dirty: boolean;
attrs: Omit<FieldAttrs, 'name'>;
}