This is the 12th day of my participation in the August Text Challenge.More challenges in August

Dynamic form requirements and implementation ideas

My project has a generic form component that internally renders a large number of form elements, such as input, checkbox, Select, Radio, and so on.

The form component displays different form elements on different pages as required.

I certainly can’t set up such a complex component manually.

So I decided to discuss with the background, through the json data returned by the background to dynamically render the page form elements, and some other inconvenient data to return, write a JSON locally.

Like this:

[{
    type: input,
    value: ' '.default: 0.describle: 'Please enter age'.size: 'middle'
},
{
    type: select,
    value: ' '.default: 'Beijing'.describle: 'Please select city'.size: 'middle'.options: ['Beijing'.'tianjin']},... ]Copy the code

We then iterate over the JSON data and render the form elements based on the Type field.

Finish writing elated.

A problem

When data is submitted, the backend authentication fails.

Open the network and see where the devil is making trouble?

It turns out that because the project is using VUE, and because all form data is defined under the form property of the data function, for example

data(){
	return {
		form: {
			username: ' '.userRole: ' '.ifLoginForbid: false. }}}Copy the code

This results in all the form data being submitted together when using AXIos, where the form is all the data shared by several pages.

Because the page dynamically generates the form elements required by the current page through various V-fors, data defined in data is not easy to judge when submitting.

If you manually write all kinds of if criteria to determine which data to submit and which data to filter, there are too many judgments, the code is cumbersome and difficult to maintain.

How to solve

So I came up with the idea of using submit as a form, heh heh heh.

Because form comes with submit to submit data according to the elements existing on the page, if we use this submit method to dynamically collect the data needed in the background, it is equivalent to adding a layer of filtering to the form defined in data, isn’t it?

Therefore, it can perfectly solve my needs.

So, the question is how to use form Submit in VUE to get data?

First, we have a form, and all the elements of the form have a name attribute.

<form action="# # # #" @submit.prevent="submitform" ref="form">
	<el-input type="text" v-model="username" name="username">
	<el-select v-model="userRole" placeholder="Please select" name=""userRole>
	    <el-option
	      v-for="item in userRoleList"
	      :key="item.value"
	      :label="item.label"
	      :value="item.value">
	    </el-option>
	</el-select>
	<el-checkbox v-model="ifLoginForbid" name="ifLoginForbid">Prohibit login?</el-checkbox>
	<input type="submit" value="" v-show="false" @click="submitform">
</form>
Copy the code

You then retrieve the data in the form form by manually calling this.submitForm ()

.methods: {
	submitform(){
              // Get the data from the corresponding form from FormData
              const formData = new FormData(this.$refs['form'])
	      const data = {}
	      // Entries return an iterator that iterates through key/value pairs in FormData
	      for (let [key, val] of formData.entries()) {
	        console.log([key, val] )
	        Object.assign(data, { [key]: val })
	      }
	      return data // {username: ''username'', userRole: 1}}}Copy the code

Doubt???? Where did my ifLoginForbid go

console.log(formData.getKey('ifLoginForbid'))
// null
Copy the code

It’s a null value, which is ridiculous.

FormData didn’t get the checkbox because it wasn’t checked.

So I’ll check the checkbox and test the wave again

console.log(formData.getKey('ifLoginForbid'))
// ''
Copy the code

Tide! It’s not scientific! It’s a null character! Shouldn’t the checkbox binding be a Boolean value?

Check the elements again, see which rogue is hurting me again.

Select * from el-checkbox where input looks like this:

<input type="checkbox" aria-hidden="false" class="el-checkbox__original" value="">
Copy the code

Is this component variation too deep? There is no probing to study. But I know that normal input looks something like this:

<input type="checkbox" :checked="checked" :name="name" @change="change" :value="checked"/>
Copy the code

So I implemented a myCheckbox component myself by following the rules above:

<template>
   <input type="checkbox" 
        :name="name" 
   	:checked="checked" 
   	:value="checked"
   	@change="change" />
</template>

<script>
export default {
  props: {
    checked: {
      type: Boolean
    },
    name: {
      type: String}},model: {
    prop: 'checked'.event: 'change'
  },
  methods: {
    change(e) {
      this.$emit('change', e.target.checked)
    }
  }
}
</script>
Copy the code

Used in the parent component:

<component :is="'myCheckbox'" v-model="checked" :name="'ifLoginForbid'" />
Copy the code

Check formdata.getKey (‘ifLoginForbid’) // true again

Yes, this time we have successfully retrieved all the form elements of the page and generated the data to submit to the background.

Nice ~ ~