Hooks running before element mounted to DOM

I’m trying to get Stripe working on a LiveView and part of that is mounting a “card element” to a DOM element. I’m using the following hook to do that:

Hooks.initStripe = {
  mounted() {
    const successCallback = (paymentIntent) => {
      this.pushEvent('payment-success', paymentIntent) 
    }
    initCheckout(this.el, successCallback)
  }
}

const stripe = Stripe('my_public_key')

const initCheckout = (element, successCallback) => {
  const elements = stripe.elements()
  const card = elements.create('card')
  card.mount('#card-element') 
}

This does not work when I put the hook on the 'card-element and it does not work when I put the hook on a random div at the very end of the template either. However, if I call the initCheckout function in a setTimeout and delay it a couple seconds it works like it is supposed to and the card input is mounted. So, I’m thinking that it is trying to run card.mount('#card-element') before that element is rendered. But, my understanding of mounted() was that it fires when the element the hook is on is mounted to the DOM. This obviously isn’t the case. Anyway, how can I make this work without using setTimeout.

Make sure you have phx-update="ignore" for the element. I checked the docs here Stripe JavaScript SDK reference – Mount an Element and mount supports DOM elements directly so I think you should use card.mount(element) instead of card.mount('#card-element') in your initCheckout.

Awesome, the phx-update="ignore" worked, thanks!