VueJS and AmazonPayButton javascript errors

Viewed 365

I'm trying to use AmazonPay in my VueJS app. I was able to get the javascript to load, but I'm getting an error when I try to display the button. It seems like there would be plenty of examples of AmazonPay out there, but nothing for VueJS.

Here is the Javascript console error:

Uncaught TypeError: Cannot read property 'getElementsByTagName' of null
    at Object.C.Button (Widgets.js:2)
    at window.onAmazonPaymentsReady (playmix.vue?4ede:39)
    at Widgets.js:2
    at Widgets.js:2
    at HTMLScriptElement.a (Widgets.js:2)

I put the javascript to be called by the Amazon javascript in the mounted section of my component:

 mounted() {
    window.onAmazonLoginReady = function () {
      amazon.Login.setClientId(
        "CLIENT_ID"
      );
    };
    window.onAmazonPaymentsReady = function () {
      showButton();
    };
    function showButton() {
      var authRequest;
      OffAmazonPayments.Button(
        "AmazonPayButton",
        "CLIENT_ID",
        {
          type: "PwA",
          color: "Gold",
          size: "medium",
          authorization: function () {
            loginOptions = { scope: "profile", popup: "false" };
            authRequest = amazon.Login.authorize(
              loginOptions,
              "https://localhost/test"
            );
          },
        }
      );
    }
    let amazonpay = document.createElement("script");
    amazonpay.setAttribute(
      "src",
      "https://static-na.payments-amazon.com/OffAmazonPayments/us/sandbox/js/Widgets.js"
    );
    amazonpay.setAttribute("type", "text/javascript");
    amazonpay.async = true;
    document.head.appendChild(amazonpay);
},

In my component I have a tag. I found a React package for AmazonPay, but so far I haven't found many examples for use in Vue. There is a full blown commerce library for Vue, but it seems overkill for my project. Any ideas on how to solve this issue?

1 Answers

I just ran into this same issue and solved it by wrapping the call to showButton() with Vue's .$nextTick() function. This will run your function once the template is done being rendered.

The following should work in your example if you just replace it inside your mounted() section.

If you can use ES6:

window.onAmazonPaymentsReady = () => {
  this.$nextTick(function(){
    showButton();
  })
};

if not, then this should work:

var that = this;
window.onAmazonPaymentsReady = function () {
  that.$nextTick(function(){
    showButton();
  })
};
Related