Add and alter a script tag within the Vue template

I am currently working on integrating a payment service into my platform. The payment service has provided me with a form that includes a script tag.

This question is a follow-up to a previous query on inserting a script tag inside a Vue template.

Here is the form for checkout from the payment service:

<form action="http://localhost:8081/api/v1/payment/" method="POST">
      <script
        src="https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js"
        data-public-key="KEY"
        data-transaction-amount="14.90">
      </script>
</form>

In the Vue.js "mounted()" lifecycle hook, I have implemented the following to dynamically add the script:

<form ref="myform">
  ...
</form>

mounted() {
  let foo = document.createElement('script');    
  foo.setAttribute("src","https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js");
  foo.setAttribute("data-transaction-amount", this.newAmount)
  this.$refs.myform.appendChild(foo);
}

However, I am facing an issue where the user is able to change the "data-transaction-amount" after the view has been mounted.

To address this, I have tried the following approach:

data:()=>({
  newAmount:0
})

watch: {
    newAmount() {
      this.modifyScript();
    },
  },
  methods: {
    modifyScript() {
      let scripts = document.getElementsByTagName("script");
      for (let i = 0; i < scripts.length; i++) {
        let script = scripts[i];
        if (script.getAttribute("src") == 'https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js') {
          // Matching script found
          script.setAttribute("data-transaction-amount", this.newAmount);
        }
      }
    },

Although the "data-transaction-amount" is updated to the new value, the payment service's checkout window still displays the original value set during "mounted()".

Answer №1

To solve the issue, one effective solution is to prompt the browser to force a reload of the javascript file whenever the amount is changed.

Here are the steps to implement this:

  1. Add a version number to the end of the URL
  2. Whenever the amount changes, remove the previously added script element (src=...?old_amount)
  3. Add a new script element (src=...?new_amount)

Check out this example below (open the browser console to see the script web-tokenize-checkout.js being redownloaded when the amount changes).

Vue.component('v-loadjs',{
    template:`
        <div>
            <p><button class="btn btn-info" v-on:click="changeAmount()">Change Amount: {{amount}}</button></p>
            <p ref="test"></p>
        </div>
    `,
    data () {
      return {
        amount: 0,
        url: 'https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js'
      }
    },
    mounted: function () {
      this.loadJS(this.amount, this.amount)
    },
    watch: {
      amount: function(newAmount, oldAmount) {
        this.loadJS(newAmount, oldAmount)
      }
    },
    methods: {
      changeAmount: function () {
        this.amount += 1
      },
      loadJS: function (newAmount, oldAmount) {
        [...document.querySelectorAll('button.mercadopago-button')].forEach(item => item.remove())
        let scripts = document.getElementsByTagName("script");
        for (let i = 0; i < scripts.length; i++) {
          if (scripts[i].getAttribute("src") == this.url + '?version=' + oldAmount) {
            scripts[i].remove()
          }
        }
        let foo = document.createElement('script');    
        foo.setAttribute("src", this.url + '?version=' + newAmount);
        foo.setAttribute("data-transaction-amount", newAmount)
        this.$refs.test.appendChild(foo);
      }
    }
})

new Vue ({
  el:'#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div class="container">
        <div class="col-lg-offset-4 col-lg-4">
            <v-loadjs></v-loadjs>
        </div>
    </div>
</div>

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

Under what circumstances is it possible to iterate through an empty array?

When defining arrays in JavaScript using Array(n), it creates an empty array. If I write the following code: Array(2).map((val) => console.log(val)) Nothing happens when running this code, but if I spread out the elements of the array into another a ...

Steps to trigger a modal (bootstrap 5) in react upon clicking a cell within the Full Calendar interface

My goal is to trigger a modal window using Bootstrap 5 (not React-Bootstrap library) when clicking on a day in the FullCalendar Component in React. I attempted to access the modal by using jQuery's $, but encountered the error message "$ is not a fun ...

Enhance Your Jekyll Site with the Minimal Mistakes Theme Plugin

Hi there! I'm relatively new to website programming and could really use some assistance. I've been attempting to integrate the jekyll-lunr-js-search (https://github.com/slashdotdash/jekyll-lunr-js-search) into the minimal-mistakes theme, but I&a ...

Having trouble populating Extjs Grid with JSON data

In this simple grid, I am attempting to display three columns - Subject ID, Subject Name, and Subject Short Name by obtaining JSON data. The data is stored in a variable called myData in JSON format, which has been received from the server. Despite pasting ...

Exploring the Use of data- Attributes in SVG Circle Elements

Looking for a way to dynamically update the color of a Circle element in your SVG when it is clicked? You can achieve this by using jQuery's .css() method in conjunction with the data-* attribute. CHECK OUT AN EXAMPLE: STYLING IN CSS svg { height ...

Pedaling back and forth along a sequence

Is there a way to implement forward and backward buttons for a clickable list without using arrays, as the list will be expanding over time? I have already achieved changing color of the listed items to red, but need a solution to navigate through the list ...

Discover the intricacies of Sails Js and Vue.js communication

Currently, I am delving into both Sails and Vue.js by developing a comprehensive REST application. Up to this point, I have successfully created a multi-step sign-up page using Vue that POSTs all necessary information to different Controllers in Sails, co ...

The controller is not receiving the isolated scope value

I have implemented angular-slider.js on a webpage where a server request is triggered upon changing the slider's value. I am looking to delay this action until the user releases the mouse button, specifically during onmouseup event. Incorporating thi ...

Add the file retrieved from Firestore to an array using JavaScript

Trying to push an array retrieved from firestore, but encountering issues where the array appears undefined. Here is the code snippet in question: const temp = []; const reference = firestore.collection("users").doc(user?.uid); firestore .collec ...

Tips for effectively nesting HTML Custom Elements visually

I'm currently working on developing a basic HTML Custom Element for incorporating trees into web pages. The code structure I'm using is quite simple, as shown below: <html-tree title="root"> <tree-node title="child1" ...

How can socket listener be dynamically added in node.js with socket.io?

Assuming you have a basic socket.io configuration set up: var app = require('http').createServer().listen(80,'127.0.5.12'), io = require('socket.io').listen(app); session = require('./local_modules/session.js'); / ...

Achieving SPA navigation compatibility with an external framework that employs innerHTML for content rendering

Within my Vue.js application, I am utilizing a bootstrap-based framework to automatically generate the HTML code for my header and navigation menu with links. This generated content is then inserted into the page by setting the innerHTML of a designated mo ...

Encountered an issue with reading null properties when trying to access 'defaultPrevented' in bootstrap 5 toast

Implementing a custom hook to display and hide toast messages is working perfectly fine when invoking showToast in the button component of the Toast, but encountering an error when using this hook outside, for example in the button component of the App. Ty ...

Exploring AngularJS 1.x: Understanding the differences between isolated scope and using require with ngModel

Throughout my experience with Angular 1.x, I have always used isolated scope in my directives. However, recently I encountered a directive that solely utilized ngModel. This made me curious about the differences and potential issues when using both methods ...

Retrieving Blocked Images with Selenium: A Step-by-Step Guide

HTML: <html> <head> <body onload="document.getElementById('a').style.display='block';"> <div id="a" align="center" onclick="document.location.reload();" style="display: block; cursor: pointer;"> <img width="9 ...

Unable to display search results with AJAX in Select2

I'm struggling with getting the desired outcomes to display in Select2 when using AJAX. Below is my code: $(document).ready(function() { $("#producto").select2({ placeholder: 'Select a product', formatResult: productForm ...

When the server reloads, an error occurs stating 'CodeMirror' is not defined when using CodeMirror with Vuejs/Nuxtjs

I've integrated CodeMirror into one of the textarea elements in my Nuxtjs/Vuejs application. I want to format the textarea to resemble XML. While the CodeMirror functions correctly at times, I encounter an error when reloading the page: Test.vue 33:1 ...

Change the spread operator in JavaScript to TypeScript functions

I'm struggling to convert a piece of code from Javascript to Typescript. The main issue lies in converting the spread operator. function calculateCombinations(first, next, ...rest) { if (rest.length) { next = calculateCombinations(next, ...res ...

Increasing a value within HTML using TypeScript in Angular

I'm working with Angular and I have a TypeScript variable initialized to 0. However, when trying to increment it using *ngFor in my .ts file, the increment is not happening (even though the loop is running correctly). my-page.html <div *ngFor=&quo ...