Listen to Events During Rendering
FormCreate supports emitting form internal events to business components, allowing you to listen and handle business logic in your component code. This decouples forms from business logic, making them more flexible and maintainable.
Get API
Before using the event API, you need to obtain the API object. The API object can be obtained through events, validation functions, hook functions, etc.
For detailed instructions, please refer to: How to Get API
Emit Events
Emit custom events in form events using the api.emit() method to pass events to business components.
Avoid Naming Conflicts with Built-in Events
Please avoid using FormCreate's built-in event names as custom event names, otherwise they may conflict with built-in events.
Common built-in events include:
submit- Form submission eventchange- Form data change eventupdate:modelValue- Form data update eventmounted- Form mount completion eventcreated- Form creation completion eventvalidateFail- Validation failure event
Recommendation: Use meaningful custom event names such as formSubmit, fieldChange, dataLoaded, etc., to avoid conflicts with built-in events.
1. Emit Event in Button Click Event:
{
type: 'button',
field: 'submitBtn',
title: 'Submit',
on: {
click: function($inject) {
// Ensure getting the top-level form's API
const api = $inject.api.top;
// Get form data
const formData = api.formData();
// Emit submit event, passing form data
api.emit('formSubmit', formData);
}
}
}2. Emit Event When Field Changes:
{
type: 'input',
field: 'username',
title: 'Username',
on: {
change: function($inject) {
// Ensure getting the top-level form's API
const api = $inject.api.top;
const value = $inject.args[0];
// Emit field change event
api.emit('fieldChange', {
field: 'username',
value: value
});
}
}
}Listen via Template Syntax
When rendering forms, listen to events emitted by forms using Vue's event listening syntax @eventName and handle business logic in your components.
1. Listen to Form Submit Event:
<template>
<form-create
v-model="formData"
v-model:api="fApi"
:rule="rule"
@formSubmit="handleFormSubmit"
/>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const formData = ref({});
const fApi = ref(null);
const rule = ref([
{
type: 'button',
field: 'submitBtn',
title: 'Submit',
on: {
click: function($inject) {
const api = $inject.api;
api.emit('formSubmit', api.formData());
}
}
}
]);
// Handle form submission
async function handleFormSubmit(formData) {
try {
const response = await axios.post('/api/submit', formData);
console.log('Submit successful:', response.data);
// Show success message
if (fApi.value && fApi.value.message) {
fApi.value.message('Submit successful', 'success');
}
} catch (error) {
console.error('Submit failed:', error);
// Show error message
if (fApi.value && fApi.value.message) {
fApi.value.message('Submit failed', 'error');
}
}
}
</script>2. Listen to Field Change Event:
<template>
<form-create
v-model="formData"
v-model:api="fApi"
:rule="rule"
@fieldChange="handleFieldChange"
/>
</template>
<script setup>
import { ref } from 'vue';
const formData = ref({});
const fApi = ref(null);
const rule = ref([
{
type: 'input',
field: 'username',
title: 'Username',
on: {
change: function($inject) {
const api = $inject.api;
api.emit('fieldChange', {
field: 'username',
value: $inject.args[0]
});
}
}
}
]);
// Handle field change
function handleFieldChange({ field, value }) {
console.log(`Field ${field} changed to:`, value);
// Execute business logic based on field change
if (field === 'username') {
// Check if username is available
checkUsernameAvailability(value);
}
}
function checkUsernameAvailability(username) {
// Business logic: check if username is available
console.log('Check username:', username);
}
</script>3. Listen to Multiple Events:
<template>
<form-create
v-model="formData"
v-model:api="fApi"
:rule="rule"
@formSubmit="handleFormSubmit"
@formValidate="handleFormValidate"
@dataLoaded="handleDataLoaded"
@dataLoadError="handleDataLoadError"
/>
</template>
<script setup>
import { ref } from 'vue';
const formData = ref({});
const fApi = ref(null);
const rule = ref([
// Form rules
]);
// Handle form submission
function handleFormSubmit(formData) {
console.log('Form submitted:', formData);
// Business logic
}
// Handle form validation
function handleFormValidate({ valid }) {
console.log('Validation result:', valid);
// Business logic
}
// Handle data loading completion
function handleDataLoaded({ field, data }) {
console.log(`Field ${field} data loaded:`, data);
// Business logic
}
// Handle data loading error
function handleDataLoadError({ field, error }) {
console.error(`Field ${field} data loading failed:`, error);
// Error handling logic
}
</script>Listen via API Method
After obtaining the API object, dynamically listen to events through the api.bus.$on() method. This approach is more flexible and can register event listeners at any lifecycle of the component:
<template>
<form-create
v-model="formData"
v-model:api="fApi"
:rule="rule"
/>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const formData = ref({});
const fApi = ref(null);
const rule = ref([
{
type: 'button',
field: 'submitBtn',
title: 'Submit',
on: {
click: function($inject) {
$inject.api.emit('formSubmit', $inject.api.formData());
}
}
}
]);
// Event handler function
function handleFormSubmit(formData) {
console.log('Form submitted:', formData);
// Handle business logic
}
// Register listener when component is mounted
onMounted(() => {
if (fApi.value) {
fApi.value.on('formSubmit', handleFormSubmit);
}
});
// Remove listener before component unmounts (optional)
onBeforeUnmount(() => {
if (fApi.value) {
fApi.value.off('formSubmit', handleFormSubmit);
}
});
</script>Notes
Important Notes
- Avoid naming conflicts with built-in events: Do not use FormCreate's built-in event names (such as
submit,change,update:modelValue,mounted,created, etc.) as custom event names, otherwise they will conflict with built-in events, causing unexpected behavior - Event names: Event names are strings. It's recommended to use meaningful names such as
formSubmit,fieldChange,dataLoaded, etc., using camelCase naming - Event parameters:
api.emit()can pass multiple parameters, which will be passed to the event handler function - Listening timing: When using
api.bus.$on(), ensure the API object has been initialized. It's recommended to register inwatchoronMounted - Memory leaks: If using
api.bus.$on()to register listeners, it's recommended to remove listeners usingapi.bus.$off()when the component unmounts to avoid memory leaks - Choosing between two methods:
- Template event listening: Suitable for direct declaration in component templates, code is clearer, Vue automatically handles cleanup
- API method listening: Suitable for dynamic registration and removal, more flexible, but requires manual management


