4

I'm trying to make a dynamic form using Vue. User clicks the add button and another row appears for them to add data. The problem is, i initially set only 1 row at first but , when i put the v-for on the div, 3 extra rows started appearing. I'm confused as to why that happened? Plus, nothing happen when i click the add button. Thanks.

Dynamic vue form enter image description here

Componenet

<div class="container">
<title>exportDATA | Web to Excel</title>
<div class="mt-4">
        <div class="jumbotron bg-dark col-md-10 offset-md-1">
                <div class="card card-body bg-dark" v-for="(user,index) in users" :key="index">
                   <form>
                        <div class="row">
                            <div class="form-group col-md-3">
                                <label for="email" class="text-white">Username:</label>
                                <input type="text" class="form-control" id="username" v-model="user.username">
                            </div>
                            <div class="form-group col-md-3">
                                <label for="pwd" class="text-white">Password:</label>
                                <input type="password" class="form-control" id="password" v-model="user.password">
                            </div>
                            <div class="form-group col-md-3">
                                <label for="pwd" class="text-white">Phone Number:</label>
                                <input type="text" class="form-control" id="phone" v-model="user.phone">
                            </div>
                            <div class="form-group col-md-3">
                                <label for="pwd" class="text-white">Email</label>
                                <input type="email" class="form-control" id="email" v-model="user.email">
                            </div>
                        </div>
                    </form>
                </div>            
             <br>
                <button class="btn btn-secondary float-right" title="Click to add row"><span class="fa fa-plus-square" @click="addMoreData(index)" v-show="index == users.length-1"></span> &nbsp;Add More Data</button>
        </div>

        <div class="jumbotron bg-dark col-md-10 offset-md-1 ">
            <button class="btn btn-success col-md-6 offset-md-3 p-3"><span class="fa fa-plus-square"></span> &nbsp;Export to Microsoft Excel</button>
        </div>            
</div>
</div>

Script

    export default {
    data(){
      return{   
          users:{
              username:'',
              password:'',
              email:'',
              phone:''
          }
      }
    },
    methods:{
        addMoreData(index){
            this.users.push({ 
                username: '',
                password:'',
                email:'',
                phone:''
                });
        }

    },
    mounted() {
        console.log('Component mounted.')
    }
}
1
  • users is an ‘Object’, not an array - push is not ok in ‘addMoreData()’ Commented Jun 1, 2019 at 5:29

3 Answers 3

1

Your data should be an array that contains objects as items. In your example, v-for directive iterate properties in one object.

data(){
      return{   
          users: [{
              username:'',
              password:'',
              email:'',
              phone:''
          }]
      }
    },
Sign up to request clarification or add additional context in comments.

Comments

0

Or use vue-autoextra, and avoid having to add a button add something to a collection:

Vue.config.devtools = false
Vue.config.productionTip = false
const app = new Vue({
  el: '#app',
  data () {
    return {
      users: [
        { name: 'Alice', password: 'xyz' },
      ]
    }
  },
  components: {
    Autoextra
  }
})
@import "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.css";
.last {
  opacity: .5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-autoextra.min.js"></script>

    <div class="container" id="app">
      <div class="columns">
        <div class="column">
          <autoextra :collection="users" v-slot="{item,last,index}">
            <div class="columns is-mobile" :class="{last: last}">
              <div class="field column">
                <div class="control">
                  <label class="label">{{last ? 'New ' : ''}}User {{!last ? index + 1 : ''}}</label>
                  <input class="input" type="text" v-model="item.name"/>
                </div>
              </div>
              <div class="field column">
                <label class="label">Password</label>
                <div class="control">
                  <input class="input" type="password" v-model="item.password"/>
                </div>
              </div>            
            </div>
          </autoextra> 
        </div>
        <div class="column">
          <pre>{{users}}</pre>
        </div>

      </div>
    </div>

Comments

0
<button class="btn btn-secondary float-right" title="Click to add row">
<span class="fa fa-plus-square" @click="addMoreData(index)" v-show="index == users.length-1"></span> &nbsp;Add More Data
</button>

Why did you put @click="addMoreData(index)" inside <span> element ? It doesn't make any sense ... and it certainly won't work! Are index and users variables accessible here ? They're not!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.