Preface

This post introduces our form solutions @femessage/el-form-renderer, showing how we solve form problems with vue.js:

Form items dynamically display or hidden

Form data linkage

Form input/output data formatting

Developing custom form items

Complex form validation

Solutions

Form items dynamically display or hidden

Using hidden to control the show or hide a form item.

<template>

<el-form-renderer ref="form" :content="content" />

</template> <script>

export default {

name: 'hidden',

data() {

return {

content: [

{

type: 'select',

id: 'selected',

label: 'Select Item',

options: [

{

label: 'Option A',

value: 'optionA'

},

{

label: 'Option B',

value: 'optionB'

}

]

},

{

label: 'Data',

type: 'input',

id: 'data',

el: {

placeholder: 'content about Option B'

},

hidden: form => form.selected !== 'optionB' // hidden if you selected option B

},

]

}

}

}

</script>

Form data linkage (on)

Using on to bind blur , focus and other events to achieve form data linkage.

For example, automatically filling lastName after typing fullName

<template>

<el-form-renderer ref="form" :content="content" />

</template> <script>

export default {

data() {

return {

content: [

{

label: 'fullname',

type: 'input',

id: 'fullName',

on: {

blur: ([event], updateForm) => {

const value = event.target.value

const lastName = value.split(' ')[1] // split value by space

updateForm({ lastName }) // update Form

},

},

},

{

label: 'lastname',

type: 'input',

id: 'lastName',

}

]

}

}

}

</script>

Input/output formatting (inputFormat/outputFormat)

Take date range picker as an example. The output value of this component is string, but the backend api needs two fields {startDate, endDate}. At this point, the data needs to be formatted.

InputFormat

Convert backend api data into component expected format

<script>

export default {

data() {

return {

content: [

{

el: {

type: 'daterange',

placeholder: 'select date',

valueFormat: 'yyyy-MM-dd'

},

type: 'date-picker',

id: 'date',

label: 'Date',

// input data: startDate: '2019-07-23', endDate:'2019-07-24'

// after formatting: [ '2019-07-23', '2019-07-24' ]

inputFormat: row => ([row.startDate, row.endDate])

}

]

}

}

}

</script>

OutputFormat

Convert the output data into backend api expected format

<script>

export default {

data() {

return {

content: [

{

el: {

type: 'daterange',

placeholder: 'select date',

valueFormat: 'yyyy-MM-dd'

},

type: 'date-picker',

id: 'date',

label: '日期',

// component data: date: [ '2019-07-23', '2019-07-24' ]

// after formatting: {startDate: '2019-07-23', endDate: '2019-07-24'}

outputFormat: (val) => {

if (!val) {

return {startDate: '', endDate: ''}

}

return {

startDate: val[0],

endDate: val[1]

}

}

}

]

}

}

}

</script>

Developing custom form items(component)

In some scenario, for personalized needs, such as rendering an upload component, common form items can not meet the demand. You may want to develop a custom form item. At this time, the component option can help.

component can render custom component, and the key point of writing custom component is to implement v-model inside the component :

a props name value

emit input event

Here is an example

<!-- 自定义组件 my-input -->

<input :value="value" @input="onInput"> <script>

export default {

props: {

value: String

},

methods: {

onInput(val) {

this.$emit('input', 'my-input: ' + val)

}

}

}

</script>

Now @femessage/el-form-renderer can render this custom input component via component option

<template>

<el-form-renderer :content="content"/>

</template> <script>

import MyInput from '@/components/my-input.vue'

export default {

data() {

return {

content: [

{

// rendering MyInput

component: MyInput,

id: 'myInput',

label: 'label'

}

]

}

},

}

</script>

Here is a list of components that we can use @femessage/el-form-renderer to render without writing template.

Upload component https://github.com/FEMessage/upload-to-ali

Rich text editor https://github.com/FEMessage/v-editor

Provincial city picker https://github.com/FEMessage/el-select-area

Number range input https://github.com/FEMessage/el-number-range

Version number input https://github.com/FEMessage/el-semver-input

Complex form validation (rules)

A complex form item configuration often needs to define some rules to check user input. And there may also be some validation in the rules. Gernerally, this will cause configurations becomes very long.

The solution is set validation rules internally in custom components. Hiding configurations inside, so developers can no longer care about the validation rules, just import the component and use it.

Here’s an example showing how a custom component (basic input) set validation rules as following:

Null values are not allowed

Must input at least 3 number

Must start with 123

<template>

<el-input :value="value" @input="onInput"/>

</template>

<script>

export default {

rules() {

return [

{

required: true,

validator: (rule, val, callback) => {

if (!val) {

callback(new Error('is required!'))

} else if (!val.length >= 3) {

callback(new Error('must input at least 3 number!'))

} else if (!/^123/.test(val)) {

callback(new Error('must start with 123!'))

} else {

callback()

}

}

}

]

},

props: ['value'],

methods: {

onInput(val) {

this.$emit('input', val)

}

}

}

</script>

Conclusion

We use @femessage/el-form-renderer in every team and every project. You can find more detail in github

It’s welcome everyone to use it to speed up developing productivity~