2

I have created a table and in the table I am looping through an array of objects.

    <table class="table table-striped" v-if="bins.length > 0">
        <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col">Location</th>
            <th scope="col" class="text-end">Action</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(bin, index) in bins" :key="index">
            <th scope="row">{{index + 1}}</th>
            <td ref="txtLocaton" contenteditable="false" v-text="bin.binlocation"></td>
            <td class="text-end">
            <div class="action-btn">
                <button @click="btnEdit"><fa icon="edit" /> Edit</button>
                <button><fa icon="trash" /> Delete</button>
            </div>
            </td>
        </tr>
        </tbody>
    </table>

What I would like is that on the Edit button click, I want to change the contenteditable attribute from false to true.

This is the code for the data()

<script>
export default {
    data(){
        return{
            bins:[
                {
                    binlocation: '11 Garden Block, New City',
                },
                {
                    binlocation: 'Ali Towers, Lahore'
                },
                {
                    binlocation: 'The Mall Road'
                }
            ]
        }
    },

    methods:{
        btnEdit(){
          console.log(this.$refs.txtLocaton)
        }
    }
}
</script>

I am thinking about changing the attribute using ref but when I console it, it is returning the last array on button click

2 Answers 2

3

You may store contenteditable keys in bins array (false initially?):

[{
  binlocation: '11 Garden Block, New City',
  contenteditable: false,
}, {
  binlocation: 'Ali Towers, Lahore',
  contenteditable: false,
}, ...]

Then bind contenteditable td attribute to those values (instead of passing false directly):

<td ref="txtLocaton" :contenteditable="bin.contenteditable" v-text="bin.binlocation"></td>

And simply toggle values as you wish when 'edit' button pressed:

<button @click="bin.contenteditable = !bin.contenteditable"><fa icon="edit" /> Edit</button>

or

<button @click="btnEdit(index)"><fa icon="edit" /> Edit</button>
btnEdit(index) {
  this.bins[index] = !this.bins[index]; 
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you. BTW I am also trying to make this text focus when the user clicks on the button. Please help me out with that also. I am trying this using refs like so this.$refs.txtLocaton.focus(); but I am not sure how to pass the index
@MuhammadAmeenSheikh let me clarify, you need to focus td/tr when user clicked on 'Edit' button, right? It might happen 'cause neither td or tr DOM elements is "focusable". You can check docs here.
@MuhammadAmeenSheikh maybe solution you are looking for is add own styles to new class (to simulate focus) and toggle this class on target elements like with contenteditable attribute. I mean something like: <td ref="txtLocaton" :contenteditable="bin.contenteditable" v-text="bin.binlocation" v-class="{ focusClass: bin.contenteditable }"></td> where focusClass - your implementation.
I am trying to add the class to it like you suggested. this.$refs.locTxt.classList.add('focusable') The class gets added but it is added to the last element in the array. I now know that I have to pass the index but I am not sure how to pass it using $refs
@MuhammadAmeenSheikh I'm not sure you need to use $refs. You can access DOM element you interacted with, using $event, this way is simpler. Please, check $event docs here.
1

Try like following snippet (You can pass index to your method and bind contenteditable attribute to data property):

new Vue({
  el: '#demo',
  data(){
    return{
      bins:[
        {binlocation: '11 Garden Block, New City',},
        {binlocation: 'Ali Towers, Lahore'},
        {binlocation: 'The Mall Road'}
      ],
      editable: null
    }
  },
  methods:{
    btnEdit(index){
      this.editable = index
    }
  }
})

Vue.config.productionTip = false
Vue.config.devtools = false
.editable {
  border: 2px solid violet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <table class="table table-striped" v-if="bins.length > 0">
    <thead>
      <tr>
        <th scope="col">#</th>
        <th scope="col">Location</th>
        <th scope="col" class="text-end">Action</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(bin, index) in bins" :key="index">
        <th scope="row">{{index + 1}}</th>
        <td ref="txtLocaton" :contenteditable="index === editable" :class="index === editable && 'editable'" v-text="bin.binlocation"></td>
        <td class="text-end">
        <div class="action-btn">
          <button @click="btnEdit(index)"> Edit</button>
          <button> Delete</button>
        </div>
        </td>
      </tr>
    </tbody>
  </table>
</div>

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.