Search code examples
javascriptvuejs2vue-routerrouterlink

Vue.js replace hashtags in text with <router-link>


I receive some text from server which may contain some hashtags and when displaying this text I would like to convert these tags with links.

Example text is: "Today #weather is very nice"

Following code converts the string to

Today <router-link to="/tag/weather">#weather</router-link> is very nice

but it is not rendered again to <a> tag.

<template>
       <p v-html="content"/>
</template>

<script>
export default {
    methods: {
        convertHashTags: function(str) {
            return str.replace(/#([\w]+)/g,'<router-link to="/tag/$1">#$1</router-link>')
        }
    },
    data() {
        return{
             content: 'Today #weather is very nice'
        };
    }

</script>

How can I re-render content?

I tried https://codepen.io/movii/pen/WORoyg this approach but it expects whole string to be a single link not some text and some links.


Solution

  • Your code seems to fit ok into the dynamic-link component.

    console.clear()
    
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
    const Weather = { template: '<div>weather</div>' }
    
    const routes = [
      { path: '/foo', component: Foo },
      { path: '/bar', component: Bar },
      { path: '/tag/weather', component: Weather },
    ]
    
    Vue.component('dynamic-link', {
      template: '<component v-bind:is="transformed"></component>',
      props: ['text'],
      methods: {
        convertHashTags: function(str) {
          const spanned = `<span>${str}</span>`
          return spanned.replace(/#([\w]+)/g,'<router-link to="/tag/$1">#$1</router-link>')
        }
      },
      computed: {
        transformed () {
          const template = this.convertHashTags(this.text);
          return {
            template: template,
            props: this.$options.props
          }
        }
      }
    })
    
    const router = new VueRouter({ routes })
    
    const app = new Vue({ 
      router,
      data () {
        return {
          text: 'Today #weather is very nice'
        }
      }
    }).$mount('#app');
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    
    <div id="app">
      <router-link to="/bar">Go to Bar</router-link> |
      <dynamic-link :text="text"></dynamic-link>
       
      <router-view></router-view>
    </div>