3

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?

jeffgus
  • 61
  • 4
  • Do you have `
    ` in the template?
    – Daniel_Knights Aug 21 '20 at 07:52
  • Also, you might need to set the script in `created` instead of mounted. You're appending it after calling the different Amazon functions – Daniel_Knights Aug 21 '20 at 07:54
  • @Daniel_Knights I thought I had already tried within created. I just moved the code back to created and I get the same error. The exact line within Amazon's Widgets.js is: `}, H = M.getElementsByTagName("img"), k = 0; k < H.length; k++)` – jeffgus Aug 21 '20 at 08:01
  • Did you move just the script section of the code into `created` or the entire thing? – Daniel_Knights Aug 21 '20 at 08:04
  • @Daniel_Knights Yes, I have
    within the
    – jeffgus Aug 21 '20 at 08:04
  • @Daniel_Knights I moved everything that is shown in the post to the `created` section. – jeffgus Aug 21 '20 at 08:05
  • Leave the rest in `mounted` and try the `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 `created` – Daniel_Knights Aug 21 '20 at 08:06
  • @Daniel_Knights No difference. Same error when the Widgets.js script is loaded within the `created` section. – jeffgus Aug 21 '20 at 08:09
  • 1
    Ah ha! I put the `
    ` in the index.html of the Vue app and it shows up now! So this seems to have something to do with how Vue is building out the tag within the component.
    – jeffgus Aug 21 '20 at 18:42

1 Answers1

1

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();
  })
};
Chad
  • 1,708
  • 1
  • 25
  • 44