Extending Form Components
In FormCreate, you can easily convert custom Vue components into form components and use them just like built-in form components. This guide helps you understand how to generate custom form components and demonstrates their usage in actual business scenarios.
Note
Form components need to listen to modelValue changes and synchronously update internal values, while submitting internal value changes to the parent component through the update:modelValue event.
Encapsulating Components
Create a new Input.vue file and develop the functionality of the input box component.
<template>
<el-input :disabled="disabled" :modelValue="modelValue" @update:modelValue="handleChange" v-bind="$attrs">
<!--Custom component slots-->
<template #prepend>Http://</template>
</el-input>
</template>
<script>
import {defineComponent} from 'vue';
export default defineComponent({
name: 'FcInput',
data() {
return {};
},
emits: ['update:modelValue', 'change'],
props: {
//Get form data
modelValue: String,
//Support form disabled functionality
disabled: Boolean,
//FormCreate automatically injects some useful parameters
//into formCreateInject when generating custom components
formCreateInject: Object,
},
methods: {
//Update form data
handleChange(val) {
this.$emit('update:modelValue', val);
//Trigger change event
this.$emit('change', val);
}
}
});
</script>Predefined Component Properties and Events
To make your custom component act as a form component in FormCreate, you need to ensure that the component implements the basic functionality of v-model. This means the component needs to receive and manage modelValue and disabled states, and trigger the update:modelValue event when values change.
Props Reception Inside the custom component, ensure the following properties are received through props:
// Vue component example
{
props: {
modelValue: String, // Bound form value
disabled: Boolean // Component disabled state
}
}Trigger Events When the value inside the component changes, notify external value updates through the update:modelValue event:
this.$emit('update:modelValue', newValue);Mounting Form Components
Before generating forms, you need to ensure that custom components are mounted through global or local methods.
Global Mounting
Global mounting applies to the entire Vue application. Through this method, components can be used anywhere in the application.
app.component('FcInput', FcInput);Local Mounting
Local mounting applies to specific form instances. This method makes components available only in specific forms, using the formCreate.component() method for mounting.
formCreate.component('FcInput', FcInput);Generating Form Components
To generate custom form components in forms, you need to define the field property in the generation rule, which is a required property for form components.
const rule = {
type:'FcInput',
value:'test',
field:'testField',
title:'Input Box'
}Examples
Custom Counter Button Component
Simple Input Box Component
This is a basic custom input box component.
<template>
<input :value="modelValue" @input="updateValue" :disabled="disabled" />
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
modelValue: String,
disabled: Boolean
});
const emit = defineEmits(['update:modelValue']);
const updateValue = (event) => {
emit('update:modelValue', event.target.value);
};
</script>Custom Selector Component
This is a custom selector component that lets users select a value from given options.
<template>
<select :value="modelValue" @change="onChange" :disabled="disabled">
<option v-for="option in options" :key="option.value" :value="option.value">
{{ option.label }}
</option>
</select>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
modelValue: [String, Number],
disabled: Boolean,
options: {
type: Array,
required: true,
},
});
const emit = defineEmits(['update:modelValue']);
const onChange = (event) => {
emit('update:modelValue', event.target.value);
};
</script>Input Box Component with Prefix and Suffix
This component demonstrates how to add prefix and suffix to an input box.
<template>
<div>
<span>{{ prefix }}</span>
<input :value="modelValue" @input="onInput" :disabled="disabled" />
<span>{{ suffix }}</span>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
modelValue: String,
disabled: Boolean,
prefix: String,
suffix: String,
});
const emit = defineEmits(['update:modelValue']);
const onInput = (event) => {
emit('update:modelValue', event.target.value);
};
</script>Custom Composite Input Component
This is a composite component that combines an input box and selector, suitable for scenarios such as selecting a country and entering a phone number.
<template>
<div>
<select :value="selectedCountry" @change="onCountryChange" :disabled="disabled">
<option v-for="country in countries" :key="country.value" :value="country.value">
{{ country.label }}
</option>
</select>
<input :value="modelValue" @input="onInput" :disabled="disabled" placeholder="Enter phone number" />
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref } from 'vue';
const props = defineProps({
modelValue: String,
disabled: Boolean,
countries: {
type: Array,
required: true,
},
});
const emit = defineEmits(['update:modelValue']);
const selectedCountry = ref(props.countries[0].value);
const onCountryChange = (event) => {
selectedCountry.value = event.target.value;
emit('update:modelValue', ''); // Clear phone number after selecting country
};
const onInput = (event) => {
emit('update:modelValue', event.target.value);
};
</script>Selector Dependent on External Data Source
This component fetches data from a remote API and populates it into a dropdown selector. Users can select an option, and the selection result will affect other parts of the form.
<template>
<div>
<label>
Select country:
<select :value="selectedCountry" @change="onCountryChange">
<option v-for="country in countries" :key="country.id" :value="country.id">{{ country.name }}</option>
</select>
</label>
<label v-if="cities.length > 0">
Select city:
<select :value="selectedCity" @change="onCityChange">
<option v-for="city in cities" :key="city.id" :value="city.id">{{ city.name }}</option>
</select>
</label>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import axios from 'axios';
// Receive props and define emits
const props = defineProps({
modelValue: {
type: Object,
default: () => ({ country: '', city: '' }),
},
});
const emit = defineEmits(['update:modelValue']);
// Define state
const countries = ref([]);
const cities = ref([]);
const selectedCountry = ref(props.modelValue.country);
const selectedCity = ref(props.modelValue.city);
// Watch selectedCountry changes
watch(selectedCountry, async (newCountry) => {
// When country changes, trigger fetching city list
await fetchCities(newCountry);
// When country changes, reset city selection
selectedCity.value = '';
emit('update:modelValue', { country: newCountry, city: '' });
});
// Watch selectedCity changes
watch(selectedCity, (newCity) => {
emit('update:modelValue', { country: selectedCountry.value, city: newCity });
});
// Get country list
onMounted(async () => {
const response = await axios.get('/api/countries');
countries.value = response.data;
if (selectedCountry.value) {
await fetchCities(selectedCountry.value);
}
});
// Get city list
const fetchCities = async (countryId) => {
const response = await axios.get(`/api/countries/${countryId}/cities`);
cities.value = response.data;
};
// Country selection event handler
const onCountryChange = (event) => {
selectedCountry.value = event.target.value;
};
// City selection event handler
const onCityChange = (event) => {
selectedCity.value = event.target.value;
};
</script>Through this documentation, you should be able to understand how to create and use custom form components in FormCreate. Custom components allow you to closely integrate business requirements with form logic, thereby building more complex and flexible form applications. Whether it's a simple input box or a complex interactive component, FormCreate can provide you with great development convenience.


