laravel - 来自 javascript (async) 的 Livewire 加载状态
问题描述
我有一个向 Stripe 发送请求的表单,以便我的用户添加付款方式:
<form id="card-form">
<label>Card details</label>
<div id="card-element"></div>
<button wire:target="addPaymentMethod" wire:loading.class="hidden" class="button round" id="card-button">Add payment card</button>
<!-- Loading spinner -->
<svg wire:target="addPaymentMethod" wire:loading class="inline-block animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</form>
(精简的)JavaScript 如下所示:
const stripe = Stripe('stripe-public-key');
const elements = stripe.elements();
const form = document.getElementById('card-form')
const cardButton = document.getElementById('card-button');
const cardElement = elements.create('card');
cardElement.mount('#card-element');
form.addEventListener('submit', async (e) => {
e.preventDefault();
cardButton.disabled = true;
const {
setupIntent,
error
} = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardNumber,
billing_details: {
name: 'Oliver'
}
}
}
);
if (error) {
// Display error.message to the user...
cardButton.disabled = false
console.log(error.message)
} else {
// The card has been verified successfully...
@this.addPaymentMethod(setupIntent.payment_method)
}
});
如果上面的 async 方法响应成功,会触发 Livewire 组件下面的方法:
public function addPaymentMethod($paymentMethod)
{
//Create the payment method in Stripe...
auth()->user()->addPaymentMethod($paymentMethod);
//Other validation etc...
}
所有这些的输出都在下面的 gif 中捕获。正如您在此处看到的,用户输入信用卡详细信息并单击“添加支付卡”并被重定向到另一个页面。
问题是,加载状态会开始一段时间,但在实际请求/重定向完成之前就消失了。
在对 Stripe 的实际请求完成之前,如何显示加载微调器?
解决方案
这取决于addPaymentMethod
您的加载状态为何提前隐藏的其他情况。为了让您更好地控制该时间,我可能会将您的加载状态的显示/隐藏推迟到 javascript 层。这里有几种方法可以解决它:
1. 使用承诺
Livewire 的一个很好的特性是,当通过 javascript 调用组件方法时,它们会在完成后返回一个 Promise。因此,如果您需要隐藏加载状态,可以在此处执行此操作:
// The card has been verified successfully...
@this.addPaymentMethod(setupIntent.payment_method)
.then(result => {
// Hide loading state
})
2. 发出事件
另一种方法是从您可以在组件前端收听的事件中发出一个事件。addPaymentMethod
public function addPaymentMethod($paymentMethod)
{
// Your add payment code runs...
// Emit an event to the frontend (with optional data)
$this->dispatchBrowserEvent('add-payment-method-complete', ['someData' => $value]);
}
您可以使用AlpineJs在前端非常简单地监听此事件。这是一个使用 Alpine 管理加载状态的简短表单示例:
<form
// Init AlpineJs with the x-data attribute
x-data="{
isLoading: false
}"
// Listen the forms submit event and change
// our "isLoading" flag to true
x-on:submit="isLoading = true">
// Listen for the event emitted from Livewire to the window
// and reset the isLoading flag to false
<svg x-on:add-payment-method-complete.window="isLoading = false" />
</form>
推荐阅读
- excel - 在用户表单之间切换时 Excel 用户表单按钮/文本重置
- vim - root 无法在 vim 8.2 中使用系统剪贴板
- scala - 如何使用列函数 scala 插入动态开发的字符串查询
- node.js - 如何使用 express 获取 html 文件的查询字符串
- c++ - 使用带有 decltype 的 std::any_cast ...为什么这段代码会抛出错误的 any_cast?
- javascript - Javascript - 获取
- python - 拆分文件 .log 字段以在 Dataframe 中使用
- google-apps-script - 谷歌工作表应用程序脚本如何复制具有相同权限的选项卡
- compatibility - 尝试使用 GeckoView 制作浏览器时出现 java.lang.ClassNotFoundException
- javascript - react中useEffect钩子的执行顺序是什么?