Syed
Syed

Reputation: 16513

How to add 'click' event listener or access 'ref' that's mentioned in JSON

Here is my data that looks something like this:

cars: [
  {
    id: 1,
    desc: 'Description with <a ref="id1" @click="openModel('my-car')">a link</a> lorem ipsum continues.'
  }, {
    id: 2,
    desc: 'Description without link'
  }, {
    id: 3,
    desc: 'Description with <a ref="id3" @click="openAnotherModel('my-dashboard')">a link</a> lorem ipsum continues.'
  }
]

In my template I can do:

<p v-for="item in cars" v-html="item"></p>

and of course this certainly not going works:

<p v-for="item in cars">{{ item }}</p>

How to access my methods/functions that's defined in my vue instance:

methods: {
  openModel(str) {
    console.log('openModel :>> ', str);
  },
  openAnotherModel(str) {
    console.log('openAnotherModel :>> ', str);
  },
},

Upvotes: 1

Views: 1449

Answers (2)

Syed
Syed

Reputation: 16513

Here is what I ended up with for the question that I have asked. Instead of figuring out how to make @click="myFun('myData')" work, I used data-image="myData"

<template lang="pug">
  div(ref="cars")
    .row.no-gutters(v-for="(item, index) in cars" :key="index")
      p(v-html="item.desc")
</template>

<script>
export default {
  data() {
    return {
      cars: [
        {
          id: 1,
          desc: 'Some text about <a href="#" onClick="return false;" class="jsOpenImgModal" data-image="/images/dash.png">dash</a> lorem ipsum continues.',
        }, {
          id: 2,
          desc: 'Description without link',
        }, {
          id: 3,
          desc: 'And, Some text about <a href="#" onClick="return false;" class="jsOpenImgModal" data-image="/image/front.png">front</a> lorem ipsum continues.',
        },
      ],
    };
  },

  mounted() {
    const imgModals = this.$refs.cars.querySelectorAll('.jsOpenImgModal');

    Object.keys(imgModals).forEach((i) => {
      const imgUrl = imgModals[i].dataset.image;
      imgModals[i].addEventListener('click', () => this.fnImgModals(imgUrl));
    });
  },

  methods: {
    fnImgModals(imgUrl) {
      console.log('dataset.image :>> ', imgUrl);
    },
  },
};
</script>

Note: Few of you may feel that this seems like un-realistic situation that any developer can encounter. cars data that I have created above is just to demonstrate what I need but I actually needed this solution for much more complicated data and for a real project.

Upvotes: 1

Fennec
Fennec

Reputation: 1882

Edited after comment.

You can access your links from the mounted event hooks, like so.

new Vue({
  el: "#app",
  data: {
    cars: [
      {
        id: 1,
        desc: `Description with <a href="my-car">a link</a> lorem ipsum continues.`
      }, {
        id: 2,
        desc: `Description without link`
      }, {
        id: 3,
        desc: `Description with <a href="dash-board">a link</a> lorem ipsum continues.`
      }
    ]
  },
  methods: {
    dispatchLink(e){
      e.preventDefault();
      const target = e.target;
      const str = target.getAttribute('href');
      
      switch(str) {
          case 'my-car':
            this.openModel(str)
            break;
          case 'dash-board':
            this.openAnotherModel(str)
            break;
          // other link type ...
        }
    },
    openModel(str) {
      console.log('openModel :>> ', str);
    },
    openAnotherModel(str) {
      console.log('openAnotherModel :>> ', str);
    }
  },
  mounted(){
      const carsLinks = this.$el.querySelectorAll('p a');
      carsLinks.forEach(link => link.addEventListener('click', this.dispatchLink)       
      )
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <p 
    v-for="car in cars" 
    :key="car.id" 
    v-html="car.desc"
    :id="car.id"
  >
  </p>
</div>

Upvotes: 4

Related Questions