Skip to main content
Version: v3

Form submitting strategy

strategy type

use hook

Before using extension hooks, make sure you are familiar with the basic usage of alova.

A hook designed for form submission. Through this hook, you can easily implement form drafts and multi-page (multi-step) forms. In addition, it also provides common functions such as form reset.

Features

  • Form drafts;
  • Multi-page (multi-step) forms;
  • Form submission automatically resets data;
  • Reset form data manually;

Usage

Basic usage

Demonstrates basic use of form hooks.

<template>
<input v-model="form.name" />
<select v-model="form.cls">
<option value="1">class 1</option>
<option value="2">class 2</option>
<option value="3">class 3</option>
</select>
<button
@click="handleSubmit"
:loading="submitting">
submit
</button>
</template>

<script setup>
import { formSubmit } from './api.js';
import { useForm } from 'alova/client';

const {
// submit status
loading: submitting,

// Responsive form data, the content is determined by initialForm
form,

// submit data function
send: submit,

// Submit successful callback binding
onSuccess,

// Submit failure callback binding
onError,

// Submit completed callback binding
onComplete
} = useForm(
formData => {
// Form data can be converted and submitted here
return formSubmit(formData);
},
{
// Initialize form data
initialForm: {
name: '',
cls: '1'
}
}
);

// submit form data
const handleSubmit = () => {
// Validate form data...
submit();
};
</script>

useForm does not send a request by default; the request is sent after you call send. The callback also receives the latest form data, so you can transform it here, or transform it inside the formSubmit function.

Caution
  1. initialForm is to set the initial form data, initialData is to set the initial response data, pay attention to the distinction;
  2. updateForm is to update the form data, and update is to update the response data, pay attention to the distinction;

The above example only shows a simple form submission function, there is no difference between ordinary form submissions, but useForm also implements more practical functions, let us continue to look down.

Submit auto reset form

Many times, we need to reset the form data after the form is submitted. We always need to manually reassign values one by one when implementing it ourselves, and useForm can help us do it automatically.

useForm(submitData, {
//...
// Set this parameter to true to automatically reset the form data after submission
resetAfterSubmitting: true
});

If you need to manually reset the form data, you can also do it by calling the reset function.

const {
// form reset function
reset
} = useForm(submitData, {
//...
});

const handleReset = () => {
reset();
};

Update form data

When editing a form, we need to display the data of the original form. At this time, we can use updateForm to asynchronously update the form data.

const {
// ...
updateForm
} = useForm(submitData, {
// ...
{
//Initialize form data
initialForm: {
name: '',
cls: '1'
}
}
});

// Request form data and update it to the form
useRequest(getData).onSuccess(({ data }) => {
updateForm({
name: data.name,
cls: data.cls
});
});

Form draft

useForm also provides a form draft function, even if the page is refreshed before the data is reset, the form data can be restored. The principle is to use the storage adapter on the alova instance to persist the form data. You only need to set store to true when using it.

useForm(submitData, {
//...
// Turn on persistence to save data. After setting to true, uncommitted data will be persisted in real time
store: true
});

Before the data is persisted, JSON.stringify converts it into a JSON string, so the form data is serialized by default. useForm has built-in serializers for Date and RegExp instances, which are handy when using time pickers.

When your form data only involves Date and RegExp instances, you don't need to do anything more. But if you have other non-JSON data, such as moment instances, you need a custom serializer. Don't worry — it is very simple, as the following moment serializer shows.

import moment from 'moment';
const momentSerializer = {
// forward is called when serializing
// Need to judge whether it is a moment instance, if it is not the target value, return undefined, indicating that it will not be processed
forward: data => moment.isMoment(data) ? data.valueOf() : undefined,

// backward is called during deserialization, data is the value returned in forward
backward: timestamp => moment(timestamp);
};

useForm(
submitData,
{
store: {
enable: true,
serializers: {
moment: momentSerializer
}
}
}
);

Multi-page/multi-step forms

Often you split a form across multiple pages or steps and submit it all at the end — for example, multi-step registration or a questionnaire. Multi-step forms may depend on each other, which is troublesome to implement by hand. useForm shares form data, so the same data is available in different pages or components. This solves the multi-step dependency and lets you submit directly without gathering the data yourself.

When using, you need to set the id through useForm, and you can share the same form data between different pages with the same id. For example, we have a form that needs to go through 3 steps to fill out the form, and they will go through component A, component B, and component C respectively.

Component A -> Component B -> Component C

At this point, we can initialize the form data inside component A:

const returnStates = useForm(submitData, {
initialForm: {
step1Input: '',
step2Input: '',
step3Input: ''
},
id: 'testForm'
});
const { form, send } = returnStates;

In component B and component C, you can get the shared data by specifying the same id as component A.

const returnStates = useForm(submitData, {
id: 'testForm'
});
const { form, send } = returnStates;

The returnStates returned by id in components B and C are the same reference as the returnStates in component A. You can use the same form, or you can call send in any component to submit the form data uniformly.

additional

If your multi-step form is not in a certain order, but in random order according to certain conditions, for example:

# possible order 1
Component B -> Component A -> Component C

# possible order 2
Component A -> Component C -> Component B

# possible order 3
Component C -> Component A -> Component B

#...

In this case, you can set the same useForm config as component A in component B and C.

const returnStates = useForm(submitData, {
initialForm: {
step1Input: '',
step2Input: '',
step3Input: ''
},
id: 'testForm'
});

In this way, no matter which component is rendered first, the form with the id of testForm can be initialized, and the subsequent components will first use the initialized form data when encountering the id of testForm, and will not initialize again. This way you can initialize form data inside any component.

Conditional filter

useForm also works as a filter form for data filtering. For example, to search city information by name, set immediate=true so it queries at initialization; then call send again to re-query as needed.

const { send: searchData } = useForm(queryCity, {
initialForm: {
cityName: ''
},
immediate: true
});
Conditional Restrictions

In conditional filtering scenarios, useForm is more suitable for non-paginated list conditional queries. If you need to perform conditional queries in paginated lists, it is recommended to use Pagination Request Strategy (usePagination).

API

Hook configuration

Inherit all configurations from useRequest.

NameDescriptionTypeDefaultVersion
initialForminitial form dataany--
idform id, the data data of the same id is the same reference, which can be used to share the same form data in multi-page forms. Single page form does not need to specify idstring | number--
storeWhether to save data persistently, after setting to true, uncommitted data will be persisted in real timeboolean | StoreDetailConfig | false-
resetAfterSubmittingreset data after submissionbooleanfalse-

Responsive data

Inherit all responsive data from useRequest.

NameDescriptionTypeVersion
formform data,determined by initialFormany-

StoreDetailConfig

NameDescriptionTypeDefaultVersion
enableWhether to enable persistent databooleanrequired-
serializersA collection of custom serializers. Built-in serializers:
1. The date serializer converts dates
2. The regexp serializer converts regular expressions
You can override a built-in serializer by using the same name
Record<string | number, DataSerializer>--

DataSerializer

NameDescriptionTypeDefaultVersion
forwardSerialization function, when serializing in forward, it needs to judge whether it is the specified data, and return the converted data, otherwise return undefined or not return(data: any) => any | undefined | voidrequired-
backwarddeserialization function, deserialization data directly(data: any) => any | undefined | voidrequired-

Action function

Inherit all action functions of useRequest.

namedescriptionfunction parametersreturn valueversion
updateFormUpdate one or more form datanewForm: Partial<F> | (oldForm: F) => F)
F is initialForm type
--
resetReset to initialized data, if there is persistent data, it will also be cleared---

Event

Inherit all events from useRequest.

NameDescriptionCallback ParametersVersion
onRestoreTriggered after the persistent data is restored--