benonymus
Phoenix liveview with Stripe element not working
Hey there,
I have a liveview that is being live rendered inside a usual eex new template, and in this liveview I have this for stripe:
<%= if @show_stripe_credit_form do %>
<div class="field" phx-hook="Test">
<%= label f, "Credit Card", class: "label" %>
<div id="card-element" style="border: 1px solid #DFE0E0" class="b-r-4 p-2">
<!-- Elements will create input elements here -->
</div>
<!-- We'll put the error messages in this element -->
<p id="card-errors" role="alert" class="has-text-danger m-t-1">
</p>
</div>
<% end %>
I also have a separate file with the js which works on another page of the app without liveview element, but it doesn’t seem to hook into this one. Here is the js:
<script src="https://js.stripe.com/v3/"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
if (!document.getElementById('card-element')) {
return
}
var stripe = Stripe('<%= System.get_env("STRIPE_PUBLISHABLE_KEY") %>');
var elements = stripe.elements({
fonts: [
{
cssSrc: 'https://use.typekit.net/gjk6uuk.css',
},
],
});
var style = {
base: {
color: "#32325d",
fontFamily: 'sofia-pro, avenir next, avenir, BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", sans-serif',
},
invalid: {
color: "#FF495C",
iconColor: "#fa755a"
}
};
var card = elements.create("card", { style: style });
card.mount("#card-element");
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
let form = document.getElementById('ticket-order-form');
console.log(form)
let submitButton = document.getElementById('submit-button');
form.addEventListener('submit', (event) => {
event.preventDefault()
submitButton.disable = true;
stripe.createToken(card).then(function(result) {
if (result.error) {
// show error
errorElement = document.getElementById('card-errors')
errorElement.textContent = result.error.message
submitButton.disable = false;
} else {
// add stripeToken to form and submit
stripeTokenHandler(result.token)
}
});
});
function stripeTokenHandler(token) {
console.log(token)
hiddenInput = document.createElement('input')
hiddenInput.setAttribute('type', 'hidden')
hiddenInput.setAttribute('name', 'stripeToken')
hiddenInput.setAttribute('value', token.id)
form.appendChild(hiddenInput)
form.submit()
}
});
</script>
My question is where do I need to add this in order to be applied in the liveview every time the liveview changes, because I hide the field based on changes on the page?
Thanks!
Most Liked
sfusato
Add another event listener like the one you have for DOMContentLoaded, but for phx:page-loading-stop and on the window object.
window.addEventListener('phx:page-loading-stop', () => {
...
});
See if this gets you closer to your objective. Then, since you say you need to react every time the liveview changes, you could properly hook it up via a liveview hook.
sfusato
When you “live navigate” that piece of JS won’t be run again. For liveview pages, you could listen on this event: phx:page-loading-stop.
winescout
I had a similar issue getting some Bootstrap JS to register if they were injected into the page. With that page-loading-stop hook there, you still need to get all your markup loaded on the page before it fires. In the case that started this thread, that “<%= if … %>” is probably causing that code to render after some handle_event, and after the page-loading-stop callback.
In some cases, I’m able to use “display: none” and “display: block” instead so the code is loaded before the callback, but that doesn’t work in all cases unfortunately.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








