2

I have some items and each item has a description with a show more link at the end. On this link's click, I want to trigger a function.
However, the method triggers correctly and prints the result in the console but the updates do not trigger in the Vue template.

Here is the complete code:

   <template>
    <main>
      <div class="card" v-for="(item, index) in items" :key="index">
     
        <div class="content">
          <h3 class="card-title">{{item.name}} </h3>
          <p v-if="showMoreText[index]">{{ item.description }}</p>
            <p v-else>{{ item.description.substring(0, 100) }}...<span class="link" @click="showMore(index)">show more</span></p>
        </div>
      </div>
    </main>
  </template>

<script>
export default {
    data() {
        return {
            showMoreText: []
        }
    },
    props: {
        items: Array,
    },
    created() {
  for (let i = 0; i < this.items.length; i++) {
    this.showMoreText[i] = false;
  }
},
    methods: {
        showMore(index) {  
            this.showMoreText[index] = !this.showMoreText[index]
            // console.log(this.showMoreText[index])
                }
    },
}
</script>
Neha Soni
  • 3,935
  • 2
  • 10
  • 32
Mads
  • 117
  • 1
  • 1
  • 10
  • The code works. What is the problem? – tauzN Dec 19 '22 at 17:56
  • the items in the v-for display as expected. They contain name and description fields. The description is long enough to exceed the substring. If i print {{showMoreText[index]}} in the template, it continues to show false for all cards even after triggering the function. – Mads Dec 19 '22 at 17:58
  • 1
    I cannot post long links as comment. See my answer. – tauzN Dec 19 '22 at 18:00
  • Your code seems to work. What different do you expect? [See this example](https://sfc.vuejs.org/#eNrNVc1ymzAQfpWtTngCwql7ckimvbe33oIPBNZGsZAYSTjuMLx7VxAToE6OnXCRVrv77f/Ssh91zU8Nsi0DSBxWtcwcPqQK6EuqTKjXO1GFOEEuM2vvU5ZnpkgZnKK9NkQGglRDEKrA84oO8LQlge0R/xC/Z6RsxFqiaeVQuZkAiZSbmb3ICSeRhNrWw3OVVdh1EEHb2lK//NIGf+PZPfbGdsRJ4nIzR6zJY7EnvCsKPXDvOC/Q5kbUTmgFXZfE9QzlFQelxWsa3DZP1hmhDsE6hNv1iiA454mtMzXGI4U6Unq+51Lkx4k/wZBC8sW/QEVPSew1H+ZeJDHl7600EyqJx6ol8aSgqUoGF+mO51obBwXus0Y6aAfNInNZsLpQ/jPoGqOmLzBUdguP84zMRAB8abaQMn/epiyccyfJ8kI/KcgKRG2bCgottQErHJCmC4E6w2LuvB+QFaIWNqfEAkrhOOVvjtuFH7jx9XO4sfkcbnz7j25M6d3 – tauzN Dec 19 '22 at 18:00

1 Answers1

7

You are facing this problem because your data is not reactive.

According to the documentation-

Vue cannot detect the following changes to an array:

  1. When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
  2. When you modify the length of the array, e.g. vm.items.length = newLength

The problem you are facing is the first case and to resolve it, you need to make the data reactive using Vue.set method-

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// You can also use the vm.$set instance method, which is an alias to the global Vue.set:
this.$set(vm.items, indexOfItem, newValue)

Here's the working demo of your problem-

.link {
  color: blue;
  cursor: pointer;
}
<html>
<div id="app">
  <div class="card" v-for="(item, index) in items" :key="index">
      <div class="content">
        <h3 class="card-title">{{ item.name }}</h3>
        <p v-if="showMoreText[index]">{{ item.description }}</p>
        <p v-else>
          {{ item.description.substring(0, 10) }}...<span
            @click="showMore(index)"
            ><span class="link">show more</span></span
          >
        </p>
      </div>
    </div>
</div>

<!-- Don't forget to include Vue from CDN! -->
<script src="https://unpkg.com/vue@2"></script>
<script>
new Vue({
  el: "#app", //Tells Vue to render in HTML element with id "app"
  data() {
    return {
      showMoreText: [],
      items: [
        {
          name: "name1",
          description:
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        },
        {
          name: "name2",
          description:
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        },
        {
          name: "name3",
          description:
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        },
        {
          name: "name4",
          description:
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        },
      ],
    };
  },
  mounted() {
    for (let i = 0; i < this.items.length; i++) {
      this.showMoreText[i] = false;
    }
  },

  methods: {
    showMore(index) {
      this.$set(this.showMoreText, index, !this.showMoreText[index]);
    },
  },
});
</script>
</html>
Neha Soni
  • 3,935
  • 2
  • 10
  • 32