Dynamic input box components

Install Ant Design of Vue

First of all, the steps of creating Vue 3.0 will not be described, there are many related articles on the Internet, directly start to install dependencies, after installing please pay attention to introduce the project, for details, please refer to the official documentation of Ant Design of Vue 2.0.

// The default installation command v2 cannot be installed
npm install ant-design-vue --save
If the version is not V2, the upgrade can be performed
npm i --save ant-design-vue@next
Copy the code
//main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

/ / ant - design - vue component library
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';

const app = createApp(App);

app.use(router);
app.use(Antd);
app.mount('#app');
Copy the code

2. Create folders and files

Create a new DynamicInput directory in Components

/ / path: SRC/components/DynamicInput
Copy the code

Create a new js directory in DynamicInput

/ / path: SRC/components/DynamicInput/js
Copy the code

Create index.ts in the js directory under DynamicInput

/ / path: SRC/components/DynamicInput/js/index. The ts
Copy the code

Create a new index.vue file in DynamicInput

/ / path: SRC/components/DynamicInput/index. The vue
Copy the code

Index. vue infrastructure under DynamicInput

//src/components/DynamicInput/index.vue
<template>
    <a-row>

    </a-row>
</template>

<script lang="ts">
    import {defineComponent} from 'vue'
    export default defineComponent({
        components: {},props: {},emits: [].setup(){
            return{}}})</script>

<style scoped>

</style>
Copy the code

New SRC/view/DynamicInputPage. Vue

//src/vie/DynamicInputPage.vue
<template>
    <div>
        <DynamicInput/>
    </div>
</template>

<script>
    import DynamicTags from '@/components/DynamicInput/index.vue'
    export default {
        components:{
            DynamicInput,
        }
    }
</script>

<style scoped>

</style>

Copy the code

Third, the idea of function realization

  1. Dynamic input box total score is four parts
  • Content entry box
  • Quantity input box
  • Deletes the current row button
  • Add the next button
  1. Each is built from components in the component library
  • a-input
  • a-input-number
  • a-button && MinusOutlined
  • a-button && PlusOutlined
  1. Store each row of data through the Data array
//data data structure
[
    / / the first line
  {
    "name": "111"."count": 1
  },
   / / the second line
  {
    "name": "2222"."count": 3}]Copy the code
  1. Each row is iterated through the Data array
  • Delete current row button each row is displayed
  • Add next line button last line display
  1. Focus the newly added input box by automatically getting focus
  2. Automatically delete input fields by losing focus and determining that there is no input

Four, complete source code

  1. Under DynamicInput index. Vue
//src/components/DynamicInput/index.vue
<template>
    <div class="container">
        <a-space direction="vertical" ref="inputBoxDom" style="width: 100%" v-if="data.length>0">
            <a-row class="item-row" :gutter="20"  v-for="(item,index) in data" :key="index">
                <a-col :span="16">
                    <a-input :maxLength="20" v-model:value="item.name" @blur="inputBlur(item,index)"/>
                </a-col>
                <a-col :span="4">
                    <a-input-number :min="1" v-model:value="item.count" />
                </a-col>
                <a-col :span="4">
                    <a-space>
                        <a-button type="danger" shape="circle" @click="ItemInputDelBtn(index)">
                            <template #icon><MinusOutlined /></template>
                        </a-button>
                        <a-button type="primary" shape="circle" v-if="index+1==data.length" @click="ItemInputAddBtn(index)">
                            <template #icon><PlusOutlined /></template>
                        </a-button>
                    </a-space>
                </a-col>
            </a-row>
        </a-space>
        <a-tag v-else @click="addInput">
            <plus-outlined/>Add content</a-tag>
    </div>
</template>

<script lang="ts">
    import {defineComponent} from 'vue'
    import {PlusOutlined,MinusOutlined} from '@ant-design/icons-vue';
    import dynamicInput from './js/index';
    export default defineComponent({
        components:{
            PlusOutlined,
            MinusOutlined
        },
        emits: ['change'].setup(props,context){
            const {
                inputBoxDom,
                data,
                addInput,
                ItemInputAddBtn,
                ItemInputDelBtn,
                inputBlur,
            } = dynamicInput(props,context);

            return {
                inputBoxDom,
                data,
                addInput,
                ItemInputAddBtn,
                ItemInputDelBtn,
                inputBlur,
            }
        }
    })
</script>

<style scoped>
</style>


Copy the code
  1. Create index.ts in the js directory under DynamicInput
/ / path: SRC/components/DynamicInput/js/index. The ts
import {ref,toRaw,watch,nextTick} from 'vue'
import { message } from 'ant-design-vue';

export default function dynamicInput(props: any,context: any) {
    const inputBoxDom: any = ref(null);
    const data = ref<object[]>([]);
    // Add input
    const addInput = () = >{
        data.value.push({
            name:' '.count:1});// Auto focus input box
        nextTick(() = > {
            const dom = inputBoxDom.value;
            const lastIndex = dom.$el.children.length-1;
            console.log(dom.$el.children[lastIndex].getElementsByClassName("ant-input") [0].focus());
        });
    };
    // Input box loses focus
    const inputBlur = (item: any,index: number) = >{
        if(! item.name || ! item.name.trim()){ message.config({maxCount:1}); message.error('Please enter content');
            data.value.splice(index,1);
            return false;
        }
        return true;
    };
    // Add button to input box
    const ItemInputAddBtn = (index: number) = >{
        if(inputBlur(data.value[index],index)){
            data.value.push({
                name:' '.count:1}); }// Auto focus input box
        nextTick(() = > {
            const dom = inputBoxDom.value;
            const lastIndex = dom.$el.children.length-1;
            console.log(dom.$el.children[lastIndex].getElementsByClassName("ant-input") [0].focus());
        });
    };
    // Input box delete button
    const ItemInputDelBtn = (index: number) = >{
        data.value.splice(index,1);
    };

    watch(data.value, (newValue: any, oldValue: any) = > {
        context.emit('change',toRaw(newValue))
    });

    return {
        inputBoxDom,
        data,
        addInput,
        ItemInputAddBtn,
        ItemInputDelBtn,
        inputBlur,
    }
}

Copy the code
  1. src/view/DynamicInputPage.vue
//src/view/DynamicInputPage.vue
<template>
    <div class="container">
        <div class="formBox">
            <DynamicInput @change="inputChange" />
        </div>
        <div class="jsonCode">
            <pre>{{jsonData}}</pre>
        </div>
    </div>
</template>

<script>
    import {ref} from 'vue'
    import DynamicInput from '@/components/DynamicInput/index.vue'
    export default {
        components:{
            DynamicInput,
        },
        setup(){
            const jsonData = ref([]);
            const  inputChange = e= >{
                jsonData.value = e;
                console.log(e)
            };
            return{
                jsonData,
                inputChange
            }
        }
    }
</script>

<style scoped>
    .container{
        display: flex;
        box-sizing: border-box;
        margin: 0 auto;
        padding: 20px 10px;
        width: 100%;
        max-width: 1200px;
    }
    .formBox{
        width: 50%;
        max-width: 600px;
    }
    .jsonCode{
        box-sizing: border-box;
        padding: 20px;
        width: 50%;
        max-width: 600px;
        min-height:200px;
        background: # 333;
        color: #fff;
    }
</style>



Copy the code

Project source code: github.com/jiangzetian…

Demo video of this article: Click browse

More front-end content welcome to pay attention to the public number: day small day personal network