What is the best way to create clickable text in an HTML string and set up an @click function in VueJS 2?

I have an array of strings that I want to transform by turning certain words like "User object", "Promise", etc into clickable links. Here is the initial array:

var strings = ['This returns a promise containing a User Object that has the id', 'next string']

The desired outcome should look like this:

<div class="wrapper">
    <div class="item" v-for="str in strings" v-html="str"></div>
</div>

The challenge lies in replacing specific words like "User object", "Promise" and attaching a @click event for my application to handle.

If rendered as intended, it would appear as follows (manually recreated from the previous v-for loop example):

<div class="wrapper">
    <div class="item">This returns a <a href="#" @click.prevent="help('promise');">promise</a> containing a <a href="#" @click.prevent="help('User object');">User object</a> that has the id</div>
    <div class="item">next string</div>
 </div>

I attempted to achieve this with the following method but it did not bind the @click event:

methods: {
    linkify(str) {
       return str.replace(/user object/, '<a href="#" @click="help">User object</a>');
    }
}

Any suggestions?

Answer №1

Illustrated below is a component showcasing how it takes a string for the complete message and another string for the text to be replaced with a link. It then proceeds to render a span containing that message, with the link text enclosed within an <a> tag:

Vue.component('linkify', {
  template: '#linkify-template',
  props: {
    value: { type: String },
    linkText: { type: String }
  },
  computed: {
    before() {
      return this.value.split(this.linkText)[0];
    },
    after() {
      return this.value.split(this.linkText)[1];
    }
  }
});

new Vue({
  el: '#app',
  data() {
    return {
      message: 'This returns a promise containing a User Object that has the id',
    }
  },
  methods: {
    foo() {
      console.log('clicked')
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>

<script type="text/x-template" id="linkify-template">
  <span>
    {{ before }}
    <a href="#" @click.prevent="$emit('click')">
      <code>{{ linkText }}</code>
    </a>
    {{ after }}
  </span>
</script>

<div id="app">
  <linkify link-text="User Object" :value="message" @click="foo"></linkify>
</div>

Answer №2

Finally solved the issue. If anyone knows a more efficient method, please share!

Vue.component('linkify', {
    props: ['value', 'words'],
    template: `<span :is="html"></span>`,
    data() {
        return {
            html: Vue.compile('<span>' + this.value.replace(new RegExp('(' + this.words.join('|') + ')', 'g'), `<a href="#" @click.prevent="$parent.$emit('click', '$1')"><code>$1</code></a>`) + '</span>'),
        }
    }
});

Now I just need to implement this in the main app:

<div class="wrapper">
    <div class="item" v-for="str in strings">
        <linkify :value="str" :words="['user object', 'promise']" @click="help"></linkify>
    </div>
</div>

Unfortunately, this code only functions with the full version of Vue due to its dependency on the compile function.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for automatically filling in fields when a button is clicked in a React application

I'm attempting to pre-fill the form fields that are duplicated with data from already filled fields. When I click the "Add Fields" button, new fields are replicated, but I want them to be pre-populated with data from existing fields. How can I access ...

Rendering issue with component

I am encountered with a situation where one component is failing to render its sub-component. Surprisingly, there are no visible errors in the console. The data I'm expecting from the web call is also coming through without any issues. However, for so ...

Find the difference between array_A and the documents in array_B using MongoDB's $match operator, and return the result as Array_C

I need to create an array_C that includes only the elements from array_A that are not present in array_B. My approach involves using $match in aggregate to specify array_B. For instance: array_A = [1, 2, 3] array_B = [2, 4, 6, 8, 10] array_C = [1, 3] I a ...

How can I detect click events on SVG path element using Angular?

Is it possible to detect click events on SVG elements such as path or g using Angular? To see an example of this, check out this demo. Right now, if a (click) event binding is added to the svg elements, the click() event handler will trigger. However, how ...

Display a remote page on hover using Javascript, CSS, and HTML without providing any clickable link

How can I display a preview of another page within a div container without actually making the text clickable? I want the preview to show when the mouse hovers over specific text, but I need the original text to stay on the main page. I've experiment ...

A step-by-step guide on uploading a CSV file in Angular 13 and troubleshooting the error with the application name "my

I am currently learning angular. I've generated a csv file for uploading using the code above, but when I try to display it, the screen remains blank with no content shown. The page is empty and nothing is displaying Could it be that it's not ...

The outcomes of my JavaScript code are not aligning with my expectations

I've been experimenting with printing objects from an API using JSON and AJAX, and I noticed that the console.log works perfectly to display the output. However, I'm having a bit of trouble with my generateCreatureDiv function as it doesn't ...

Guide to implementing true and false statements within a bound class with Vue.js

I encounter multiple errors when a user provides incorrect information. My goal is to modify the border color to red when the error is true, and remove the border color when the error is false. Here is the code in question- <Datepicker :class="{ ...

The time-out counter fails to detect the input field

After writing a method to reset the timeout on mouse click, keyup, and keypress events, I realized that it does not account for input fields. This means that when I am actively typing in a field, the timeout will still occur. Below is the code snippet: ...

Control the switch for CSS selectors

Consider the following scenario where CSS rules are defined: <style> table {background:red;} div {background:green;} </style> In addition, there is HTML code that calls a JavaScript function: <table onclick="tu ...

Highlighting menu elements when landing on a page and making another menu element bold upon clicking in WordPress

I've been searching extensively for a solution to this issue. I'm trying to make the menu item DE appear bold when entering the site, and if I click on EN, I want DE to return to normal (thin) font while EN becomes bold. You can find the site he ...

Angular unable to register service worker

Looking to implement push notifications in my Angular app using vanilla JavaScript instead of the Angular service worker or @angular/pwa. In angular.json, I've specified the path to the js file under the script option. However, when the service worke ...

Ways to dynamically manipulate HTML elements in Angular 5

Recently, I've been attempting to programmatically transform an HTML element. Strangely, when I update the transform value in the console tab, it changes successfully, but for some reason it doesn't reflect in the element tab of the browser. onD ...

Using jQuery to calculate mathematical operations in a form

I've been working on creating a form that calculates the total cost based on selected options. So far, I've managed to get it working for three options, but I'm stuck on how to calculate the subtotal by adding the variables "vpageprice" and ...

Utilize Ajax.ActionLink on a DIV by incorporating data from the Model

Although there are similar questions on this topic already, they do not address the specific issue of using values from the model as arguments for the controller. Make DIV containing AJAX ActionLink clickable Div as Ajax.ActionLink Take a look at the fo ...

Using AngularJS, generate a JSON array with a specified key

Looking to create a JSON array structure with keys using AngularJS, but unsure how to push data in order to achieve this. The goal is to generate a JSON array based on the provided data below. $scope.category = [{"id": 20, "name": "vegetable"}, {"id": ...

I'm attempting to render HTML emails in ReactJS

I have been attempting to display an HTML page in React JS, but I am not achieving the same appearance. Here is the code snippet I used in React JS: <div dangerouslySetInnerHTML={{ __html: data }}/> When executed in regular HTML, the page looks lik ...

Checking the parameters passed to a function in Typescript: A step-by-step guide

Currently, I am working with Typescript and then transpiling my TS code into JavaScript. However, I have encountered an issue that I am struggling to resolve. The error message I am facing is as follows: Error Found in TypeScript on Line:2 - error TS230 ...

The issue persists with UIkit modal element remaining in the DOM even after the parent component in Vue.js is destroyed

In my Vue app, I am utilizing the UIKit modal. UIkit.modal(element).show(); // This adds the class uk-open and sets style to display:block UIkit.modal(element).hide(); When I hide the modal, it simply removes the class uk-open and the inline style of dis ...

What strategies can be implemented to decrease the initial loading duration of a YouTube iframe video?

What are some techniques we can use to decrease iframe loading time? Is it possible to implement lazy loading for YouTube iframe videos? I experimented with initially hiding the iframe and displaying an image instead. However, when the user clicks, it req ...