Chris Woehrle
Chris Woehrle

Reputation: 3

How to return a value from a table row in a v-for loop in Vue?

I want to return a value ("Title") from a table row (generated by a v-for loop) when a button in that row is clicked, but I can't figure out the correct method. I can console.log the value on click, but I can't get it to actually return a value in the browser.

I've tried many different methods and none work. I also get the following error when I use {{ clicked(row) }} to display the returned value in my HTML:

"Property or method "row" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property."

It doesn't work if I remove the "row" argument either.

This method logs the correct value to console, but does not return the value in browser:

methods: {
clicked(row) {
console.log(row.title);
return (row.title);
}

I've spent days trying to figure this out - any help greatly appreciated!

HTML

<div id="app">
    <table>
        <thead>
            <tr>
                <th>Title</th>
                <th>Price</th>
                <th>Add To Cart</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="row in rows">
                <td>{{ row.title }}</td>
                <td>{{ row.price }}</td>
                <td><button @click="clicked (row)">Add To Cart</button></td>
            </tr>
        </tbody>
    </table>
    <p>{{ clicked(row) }}</p>
</div>
</div>

JS

var app = new Vue({
el: "#app",
data: {
rows: [{
    id: 001,
    title: "Lorem",
    price: 5
  },
  {
    id: 002,
    title: "Ipsum",
    price: 23
  },
  {
    id: 003,
    title: "Dolor",
    price: 8
  },
 ]
},
methods: {
clicked(row) {
  console.log (row.title);
  return (row.title);
}
}
})

I am trying to display the value for "Title" when I click the button on its row. (And if I click both rows, I want both "Titles" to display).

I currently only get various errors.

Upvotes: 0

Views: 7714

Answers (1)

thanksd
thanksd

Reputation: 55664

You currently have clicked(row) in the <p> tag of your template. But, since you haven't defined a row property for the vue instance and you are outside of the scope of the v-for tag, you are getting the 'Property or method "row" is not defined" error.

What <p>{{ clicked(row) }}</p> is telling Vue is that, whenever the template is rendered or re-rendered, call the Vue instance's clicked method (passing the non-existent row property) and display whatever is returned by that method.

What you want is to set a value to display whenever you click one of the buttons. You should add a separate property, say displayTitle, in your data function which you can set in your clicked method. Then, just use displayTitle in your <p> tag.

Here's an example:

new Vue({
  el: "#app",
  data() {
    return {
      rows: [
        { id: 001, title: "Lorem", price: 5 }, 
        { id: 002, title: "Ipsum", price: 23 }, 
        { id: 003, title: "Dolor", price: 8 }
      ],
      displayTitle: ''
    }
  },
  methods: {
    clicked(row) {
      this.displayTitle = row.title;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <table>
    <thead>
      <tr>
        <th>Title</th>
        <th>Price</th>
        <th>Add To Cart</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in rows">
        <td>{{ row.title }}</td>
        <td>{{ row.price }}</td>
        <td><button @click="clicked(row)">Add To Cart</button></td>
      </tr>
    </tbody>
  </table>
  <p>{{ displayTitle }}</p>
</div>

** Side Note: Best practice is to always define a Vue instance using a data function which returns an object instead of a data property as in your example code.

Upvotes: 1

Related Questions