1

Ok, so i built a little app to exercise what i've learned so far with vue, but theres some things that i want to do but have no idea HOW yet

<div class="container" id="app">
  <div class="row">
    <div class="col-xs-6 jumbotron">
      <form class="form-horizontal" @submit.prevent>
        <p>
          <label>Name</label>
          <input id="inputName" type="text" class="form-control" v-model="dataToArray.name">
        </p>
        <p>
          <label>Sex</label>
          <input type="radio" name="sex" value="male" v-model="dataToArray.sex"> Male
          <input type="radio" name="sex" value="female" v-model="dataToArray.sex"> Female
        </p>
        <p>
          <label>Select a Color</label>
          <select id="selectColor" class="form-control" v-model="dataToArray.color">
            <option value="red">Red</option>
            <option value="blue">Blue</option>
          </select>
        </p>
        <p>
          <button class="btn btn-primary" @click="addToArray()">Add to Array</button>
       </p>
      </form>
    </div>
    <div class="col-xs-6">
      <table id="table" class="table table-bordered" v-if="savedData.length > 0">
        <thead>
          <th>Name</th>
          <th>Sex</th>
          <th>Color</th>
          <th></th>
        </thead>
        <tbody id="test">
          <tr v-for="(data, index) in savedData" v-if="savedData[index].status">
            <td>{{ data.name }}</td>
            <td>{{ data.sex }}</td>
            <td>{{ data.color }}</td>
            <td class="text-center">
              <button @click="editThis(index)" class="btn btn-warning">Edit</button>
              <button @click="saveEdit(index)" class="btn btn-default">Save</button>
              <button class="btn btn-danger" @click="deleteThis(index)">Delete</button>
            </td>
          </tr>
        </tbody>
      </table>
      {{ dataToArray.id }} <br>
      {{ dataToArray.name }} <br>
      {{ dataToArray.sex }} <br>
      {{ dataToArray.color }} <br>
      {{ savedData }}
    </div>
  </div>
</div>

new Vue({
    el: '#app',
  data:{
    dataToArray: {
        id: null,
      name: '',
      sex: '',
      color: '',
      status: true
    },
    savedData: []
  },
  methods: {
    addToArray(){
        this.dataToArray.id = this.savedData.lenth;
        this.savedData.push(Object.assign({}, this.dataToArray));
    },
    deleteThis(index){
        this.savedData[index].status = false;
    },
    editThis(index, event){
        document.getElementById("inputName").value = this.savedData[index].name;
      document.getElementById("selectColor").value = this.savedData[index].color;
      //check the form radio according to the current sex of the object
    },
    saveEdit(index){
        this.savedData[index].name = document.getElementById("inputName").value;
        this.savedData[index].color = document.getElementById("selectColor").value;
      //this.savedData[index].sex = get the new radio value
    }
  }
});

This is the app:https://jsfiddle.net/myrgato/10uqa1e1/5/

The edit and save button, i wanted to hide the edit button and show the saved button when the edit button is clicked, and the otherway around when the save button is clicked.

Editing the sex value of the object, i cant get the new radio value (the checked one after i click edit and select a new one)

Hiding the table if there are no rows, i am able to do that at the first time by comparing it to the size of the looping array, but when i delete rows, i dont delete the objects from the array, i just change the status, so if add one object to the array and delete it, the row will be gone (shows only if status = true) but the table will not (because even tho there are no rows, the object still exists inside the array)

Can someone help me understand how to achieve this?

Edit: Updated the code with what we got so far:

https://jsfiddle.net/myrgato/rcj3kef7/

As you can see, if i add two items to the table, and edit ONE, all the rows show the save button, how can i only show the save button of the row that i clicked?

and another one, check the following code: https://jsfiddle.net/myrgato/rcj3kef7/1/

In this one, i put the save button outside the table, in the form itself, so when the user clicks edit on a row, the save button and the current values show on the form.

The problem is, how will i get the index thats inside the v-for to my saveThis function that is outside?

2 Answers 2

3

You want to have an editing mode. When you're in editing mode, the Save button appears and the Edit button disappears; otherwise, the reverse. That's just a variable that you set to the index of the row being edited, or null when not editing.

For copying values between dataToArray and savedData, Object.assign is handy.

Since you want to hide the table when it's empty and it's empty when there are no items with a true status member, create a computed that uses find to tell you if there are any such items.

new Vue({
  el: '#app',
  data: {
    dataToArray: {
      id: null,
      name: '',
      sex: '',
      color: '',
      status: true
    },
    savedData: [],
    editing: false
  },
  computed: {
    hasVisibleData() {
      return this.savedData.find(d => d.status);
    }
  },
  methods: {
    addToArray() {
      this.dataToArray.id = this.savedData.lenth;
      this.savedData.push(Object.assign({}, this.dataToArray));
    },
    deleteThis(index) {
      this.savedData[index].status = false;
    },
    editThis(index, event) {
      this.editing = index;
      Object.assign(this.dataToArray, this.savedData[index]);
    },
    saveEdit(index) {
      this.editing = null;
      Object.assign(this.savedData[index], this.dataToArray);
    }
  }
});
.jumbotron {
  background-color: ;
}

label {
  color: ;
}
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div class="container" id="app">
  <div class="row">
    <div class="col-xs-6 jumbotron">
      <form class="form-horizontal" @submit.prevent>
        <p>
          <label>Name</label>
          <input id="inputName" type="text" class="form-control" v-model="dataToArray.name">
        </p>
        <p>
          <label>Sex</label>
          <input type="radio" name="sex" value="male" v-model="dataToArray.sex"> Male
          <input type="radio" name="sex" value="female" v-model="dataToArray.sex"> Female
        </p>
        <p>
          <label>Select a Color</label>
          <select id="selectColor" class="form-control" v-model="dataToArray.color">
            <option value="red">Red</option>
            <option value="blue">Blue</option>
          </select>
        </p>
        <p>
          <button class="btn btn-primary" @click="addToArray()">Add to Array</button>
        </p>
      </form>
    </div>
    <div class="col-xs-6">
      <table id="table" class="table table-bordered" v-if="hasVisibleData">
        <thead>
          <th>Name</th>
          <th>Sex</th>
          <th>Color</th>
          <th></th>
        </thead>
        <tbody id="test">
          <tr v-for="(data, index) in savedData" v-if="savedData[index].status">
            <td>{{ data.name }}</td>
            <td>{{ data.sex }}</td>
            <td>{{ data.color }}</td>
            <td class="text-center">
              <button v-if="editing!==index" @click="editThis(index)" class="btn btn-warning">Edit</button>
              <button v-if="editing===index" @click="saveEdit(index)" class="btn btn-default">Save</button>
              <button class="btn btn-danger" @click="deleteThis(index)">Delete</button>
            </td>
          </tr>
        </tbody>
      </table>
      {{ dataToArray.id }} <br> {{ dataToArray.name }} <br> {{ dataToArray.sex }} <br> {{ dataToArray.color }} <br> {{ savedData }}
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

7 Comments

Ohh it works great too, i found the way you wrote the computed property easier to read, but the flag idea on edit has the same problem, it only works if i have only one element on the table,if i have more than one, all the other save buttons will show! You have any idea how i would make it not?
sorry forgot to notify
Oops! Fixed. The editing flag has to indicate which row is being edited.
Now it works perfectly! How would i go if i want to but the save button outside the v-for table (like here jsfiddle.net/myrgato/rcj3kef7/1)? I need to get the index somehow so i would know which position of the array im saving in...
When you go into editing mode, you set this.editing to the index. So when you save, you can save to that index.
|
1

You would want to set a flag when one or the other is clicked that way you can change both accordingly.

new Vue ({
    data: {
        edit:[] //0 means that neither button is clicked.
    },
    methods:{
        editThis(index, event){

            this.edit[index] = 1;

            this.dataToArray.name = this.savedData[index].name;
            this.dataToArray.color = this.savedData[index].color;
            this.dataToArray.color = this.saveData[index].sex;
    },
    saveEdit(index){

        this.edit[index] = -1

        this.savedData[index].name = this.dataToArray.name
        this.savedData[index].color = this.dataToArray.color
        this.savedData[index].sex = this.dataToArray.sex
        //since we have bound the dataToArray values with v-model we can modify them from here.
   },
   addToArray(index){
       this.dataToArray.id = this.savedData.lenth;
       this.edit[index] = 0;
       this.savedData.push(Object.assign({}, this.dataToArray));
   },
})

Then in your template you want to have a "v-if" property to show and hide based on the value of the flag.

<button @click="editThis(index)" v-if="edit[index] && edit[index] > -1" class="btn btn-warning">Edit</button>
<button @click="saveEdit(index)" v-if='edit[index] && edit[index] < 1' class="btn btn-default">Save</button>

Also, in order to hide the table when there is no data you also have to use a v-if on the table itself. You can also do a computed that returns the number of elements in the array that return a status that is not equal to false like so.

new Vue({
  computed:{
    elements(){//using the ES6 arrow function syntax and Array.reduce
        return this.savedData.reduce((accum, iter) => {
          if(iter.status != false) accum += 1
        }, 0);
    }
  }
})

Then in your template you can place your table element like so:

<table id="table" class="table table-bordered" v-if="elements">

2 Comments

Awesome! The find method in a computed property worked great, but the edit flag idea works only if i have one item in the table, if i have two or more, and click edit, all the other rows will show the save button! How do i show the save button only in the row i clicked edit?
sorry forgot to notify

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.