在 Rails 6 中使用事件处理程序
Using event handlers in Rails 6
在我使用 rails 6 将条带 V3 实施到我的 Web 应用程序的过程中,我想我发现了另一个问题。当我提交表单时,我的事件处理程序似乎没有工作,这需要发生,以便我的隐藏字段可以传递到我的后端以进行条纹收费。我认为这与 turbolinks 和缓存有关?在过去的 13 个小时里,我一直在努力解决这个问题,运行今天我已经筋疲力尽了。这是我的代码,我真的需要一些帮助!
这是我认为 Javascript 应该执行的代码:
<script src="https://js.stripe.com/v3/"></script>;
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<div class="row">
<div class="col-md-9 mb-md-0 mb-5">
<%= form_for @order do |f| %>
<%= f.hidden_field 'referred_by_school', { id: "referBySchool" } %>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :customer_name, "Your Name *", class: "control-label" %><br />
<%= f.text_field :customer_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :email, "Email *", class: "control-label" %><br />
<%= f.text_field :email, class: "form-control" %>
</div>
</div>
</div>
<% if locals[:buy_method] == "group"%>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :student_name, "Student Name *", class: "control-label" %><br />
<%= f.text_field :student_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :school_name, "School or Group Name *", class: "control-label" %><br />
<%= f.text_field :school_name, class: "form-control"%>
</div>
</div>
</div>
<br>
<% end %>
<div class="col-md-2">Shipping Info</div>
<div class="col-md-6">
<div class="shipping-container">
<div class="row">
<div class="col-md-12">
<div class="md-form mb-0">
<%= f.label :street_address, "Street Address *", class: "control-label" %><br />
<%= f.text_field :street_address, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="md-form mb-0">
<%= f.label :city, "City *", class: "control-label" %><br />
<%= f.text_field :city, class: "form-control" %>
</div>
</div>
<div class="col-md-3">
<div class="md-form mb-0">
<%= f.label :state, "State *", class: "control-label" %><br />
<%= f.select :state, ['AL', 'AK', 'AS', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FM', 'FL', 'GA', 'GU', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MH', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'MP', 'OH', 'OK', 'OR', 'PW', 'PA', 'PR', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VI', 'VA', 'WA', 'WV', 'WI', 'WY' ], class: "form-control"%>
</div>
</div>
<div class="col-md-4">
<div class="md-form mb-0">
<%= f.label :zip_code, "Zip code *", class: "control-label" %><br />
<%= f.text_field :zip_code, class: "form-control" %>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.check_box :email_permission, checked: "checked", checked_value: true, unchecked_value: false %>
<%= f.label :email_permission, class: "checkbox-inline", class: "control-label" %>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :number_books, value: "Number of books to purchase *", class: "control-label" %><br />
<% if locals[:buy_method] == "group" %>
<%= f.text_field :number_books, class: "form-control", id: "groupNumberBooks" %>
<% elsif locals[:buy_method] == "individual" %>
<%= f.text_field :number_books, class: "form-control", id: "individualNumberBooks" %>
<% end %>
</div>
</div>
</div>
<% if locals[:buy_method] == "group" %>
<div class="col-md-2">
<div class="row">
<%= f.label :total, value: "Total: $", class: "control-label" %>
</div>
<div class="row">
<%= f.label :total, id: "groupTotal", class: "form-control", value: 0 %>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "group" %>
<div class="row" id="card_field1">
<div class="col-md-6">
<div id="card-element-1"><!--Stripe.js injects the Card Element--></div>
<button id="submit-1">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span>
</button>
<p id="card-errors-1" role="alert"></p>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "individual" %>
<div class="row">
<div class="form-group">
<%= f.label :total, value: "Total: $", class: "control-label" %> <br>
<%= f.label :total, id: "individualTotal", class: "form-control", value: 0 %>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "individual" %>
<div class="row" id="card_field2">
<div class="col-md-6">
<div id="card-element-2"><!--Stripe.js injects the Card Element--></div>
<button id="submit-2">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span>
</button>
<p id="card-errors-2" role="alert"></p>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
这里是应该作用于它的 Javascript(我目前将它存储在视图中,我将在它可以正常工作后处理它的重新定位)。
script>
// Create a Stripe client.
var stripe = Stripe('pk_test_****************************************************************');
// Create an instance of Elements.
var elements1 = stripe.elements();
var elements2 = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card1 = elements1.create('card', {style: style});
var card2 = elements2.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card1.mount('#card-element-1');
card2.mount('#card-element-2');
// Handle real-time validation errors from the card Element.
card1.on('change', function(event) {
var displayError1 = document.getElementById('card-errors-1');
if (event.error) {
displayError1.textContent = event.error.message;
} else {
displayError1.textContent = '';
}
});
card2.on('change', function(event) {
var displayError2 = document.getElementById('card-errors-2');
if (event.error) {
displayError2.textContent = event.error.message;
} else {
displayError2.textContent = '';
}
});
// create a token on form submission and send token to back end to create charge.
var form = document.getElementById('new_order');
form.addEventListener('submit-1', function(event) {
event.preventDefault();
stripe.createToken(card1).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors-1');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
var form = document.getElementById('new_order');
form.addEventListener('submit-2', function(event) {
event.preventDefault();
stripe.createToken(card2).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors-2');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('new_order');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
};
</script>
我知道现在有几个重复代码的实例,我会在它工作后将其擦干。此刻感觉很烦躁,因为我想我终于找到了一个适用于我的支付流程的条纹系统,现在我也 运行 解决了这个问题。更不用说我似乎无法从除视图之外的任何地方获得我的 Javascript 代码 运行ning 了……但这是另一天的问题!
这里的核心问题似乎是您正在尝试侦听一个不存在的事件 – 它称为 submit
而不是 submit-1
。换句话说:您将事件目标(= id 为 submit-1
的按钮)误认为是事件类型(= submit
)。
那么你想要做的是:
// if you want rely on having a browser that supports event.submitter,
// see https://caniuse.com/#feat=mdn-api_submitevent_submitter.
var form = document.querySelector('#new_order')
form.addEventListener('submit', function(event) {
// event.submitter gives you access to the button that submitted the form
// do what you need to do
})
// if you want to do it "the old way":
var button1 = document.querySelector('#submit-1')
var button2 = document.querySelector('#submit-2')
button1.addEventListener('click', function(event) {
// do what you need to do
})
button2.addEventListener('click', function(event) {
// do what you need to do
})
在我使用 rails 6 将条带 V3 实施到我的 Web 应用程序的过程中,我想我发现了另一个问题。当我提交表单时,我的事件处理程序似乎没有工作,这需要发生,以便我的隐藏字段可以传递到我的后端以进行条纹收费。我认为这与 turbolinks 和缓存有关?在过去的 13 个小时里,我一直在努力解决这个问题,运行今天我已经筋疲力尽了。这是我的代码,我真的需要一些帮助!
这是我认为 Javascript 应该执行的代码:
<script src="https://js.stripe.com/v3/"></script>;
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<div class="row">
<div class="col-md-9 mb-md-0 mb-5">
<%= form_for @order do |f| %>
<%= f.hidden_field 'referred_by_school', { id: "referBySchool" } %>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :customer_name, "Your Name *", class: "control-label" %><br />
<%= f.text_field :customer_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :email, "Email *", class: "control-label" %><br />
<%= f.text_field :email, class: "form-control" %>
</div>
</div>
</div>
<% if locals[:buy_method] == "group"%>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :student_name, "Student Name *", class: "control-label" %><br />
<%= f.text_field :student_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :school_name, "School or Group Name *", class: "control-label" %><br />
<%= f.text_field :school_name, class: "form-control"%>
</div>
</div>
</div>
<br>
<% end %>
<div class="col-md-2">Shipping Info</div>
<div class="col-md-6">
<div class="shipping-container">
<div class="row">
<div class="col-md-12">
<div class="md-form mb-0">
<%= f.label :street_address, "Street Address *", class: "control-label" %><br />
<%= f.text_field :street_address, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="md-form mb-0">
<%= f.label :city, "City *", class: "control-label" %><br />
<%= f.text_field :city, class: "form-control" %>
</div>
</div>
<div class="col-md-3">
<div class="md-form mb-0">
<%= f.label :state, "State *", class: "control-label" %><br />
<%= f.select :state, ['AL', 'AK', 'AS', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FM', 'FL', 'GA', 'GU', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MH', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'MP', 'OH', 'OK', 'OR', 'PW', 'PA', 'PR', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VI', 'VA', 'WA', 'WV', 'WI', 'WY' ], class: "form-control"%>
</div>
</div>
<div class="col-md-4">
<div class="md-form mb-0">
<%= f.label :zip_code, "Zip code *", class: "control-label" %><br />
<%= f.text_field :zip_code, class: "form-control" %>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.check_box :email_permission, checked: "checked", checked_value: true, unchecked_value: false %>
<%= f.label :email_permission, class: "checkbox-inline", class: "control-label" %>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="md-form mb-0">
<%= f.label :number_books, value: "Number of books to purchase *", class: "control-label" %><br />
<% if locals[:buy_method] == "group" %>
<%= f.text_field :number_books, class: "form-control", id: "groupNumberBooks" %>
<% elsif locals[:buy_method] == "individual" %>
<%= f.text_field :number_books, class: "form-control", id: "individualNumberBooks" %>
<% end %>
</div>
</div>
</div>
<% if locals[:buy_method] == "group" %>
<div class="col-md-2">
<div class="row">
<%= f.label :total, value: "Total: $", class: "control-label" %>
</div>
<div class="row">
<%= f.label :total, id: "groupTotal", class: "form-control", value: 0 %>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "group" %>
<div class="row" id="card_field1">
<div class="col-md-6">
<div id="card-element-1"><!--Stripe.js injects the Card Element--></div>
<button id="submit-1">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span>
</button>
<p id="card-errors-1" role="alert"></p>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "individual" %>
<div class="row">
<div class="form-group">
<%= f.label :total, value: "Total: $", class: "control-label" %> <br>
<%= f.label :total, id: "individualTotal", class: "form-control", value: 0 %>
</div>
</div>
<% end %>
<% if locals[:buy_method] == "individual" %>
<div class="row" id="card_field2">
<div class="col-md-6">
<div id="card-element-2"><!--Stripe.js injects the Card Element--></div>
<button id="submit-2">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span>
</button>
<p id="card-errors-2" role="alert"></p>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
这里是应该作用于它的 Javascript(我目前将它存储在视图中,我将在它可以正常工作后处理它的重新定位)。
script>
// Create a Stripe client.
var stripe = Stripe('pk_test_****************************************************************');
// Create an instance of Elements.
var elements1 = stripe.elements();
var elements2 = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card1 = elements1.create('card', {style: style});
var card2 = elements2.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card1.mount('#card-element-1');
card2.mount('#card-element-2');
// Handle real-time validation errors from the card Element.
card1.on('change', function(event) {
var displayError1 = document.getElementById('card-errors-1');
if (event.error) {
displayError1.textContent = event.error.message;
} else {
displayError1.textContent = '';
}
});
card2.on('change', function(event) {
var displayError2 = document.getElementById('card-errors-2');
if (event.error) {
displayError2.textContent = event.error.message;
} else {
displayError2.textContent = '';
}
});
// create a token on form submission and send token to back end to create charge.
var form = document.getElementById('new_order');
form.addEventListener('submit-1', function(event) {
event.preventDefault();
stripe.createToken(card1).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors-1');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
var form = document.getElementById('new_order');
form.addEventListener('submit-2', function(event) {
event.preventDefault();
stripe.createToken(card2).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors-2');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('new_order');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
};
</script>
我知道现在有几个重复代码的实例,我会在它工作后将其擦干。此刻感觉很烦躁,因为我想我终于找到了一个适用于我的支付流程的条纹系统,现在我也 运行 解决了这个问题。更不用说我似乎无法从除视图之外的任何地方获得我的 Javascript 代码 运行ning 了……但这是另一天的问题!
这里的核心问题似乎是您正在尝试侦听一个不存在的事件 – 它称为 submit
而不是 submit-1
。换句话说:您将事件目标(= id 为 submit-1
的按钮)误认为是事件类型(= submit
)。
那么你想要做的是:
// if you want rely on having a browser that supports event.submitter,
// see https://caniuse.com/#feat=mdn-api_submitevent_submitter.
var form = document.querySelector('#new_order')
form.addEventListener('submit', function(event) {
// event.submitter gives you access to the button that submitted the form
// do what you need to do
})
// if you want to do it "the old way":
var button1 = document.querySelector('#submit-1')
var button2 = document.querySelector('#submit-2')
button1.addEventListener('click', function(event) {
// do what you need to do
})
button2.addEventListener('click', function(event) {
// do what you need to do
})