Skip to content

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 event
  • change - Form data change event
  • update:modelValue - Form data update event
  • mounted - Form mount completion event
  • created - Form creation completion event
  • validateFail - 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:

js
{
  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:

js
{
  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:

vue
<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:

vue
<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:

vue
<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:

vue
<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

  1. 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
  2. Event names: Event names are strings. It's recommended to use meaningful names such as formSubmit, fieldChange, dataLoaded, etc., using camelCase naming
  3. Event parameters: api.emit() can pass multiple parameters, which will be passed to the event handler function
  4. Listening timing: When using api.bus.$on(), ensure the API object has been initialized. It's recommended to register in watch or onMounted
  5. Memory leaks: If using api.bus.$on() to register listeners, it's recommended to remove listeners using api.bus.$off() when the component unmounts to avoid memory leaks
  6. 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