I am trying to build a Login-Modal with Alpine JS. The modal is shown initally when opening the page. I define it like:
<div x-data="login()" x-show="showLoginModal" x-cloak x-transition>
<form action="/token" method="POST" @submit.prevent="submitData">
<!-- defining the login form -->
</form>
</div>
The corresponding Javascript part looks like this (leaving out some variables concerned with the data of the form.):
<script>
let token = undefined
let showLoginModal = false
function login() {
async submitData() {
await fetch(await fetch('/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formBody
})
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("Login failed.");
}
}).then((data) => {
token = data.access_token
showLoginModal = false
})
}
}
</script>
What I am trying to achieve here is that the modal is closed at this point. However although the variable is correctly set to false, the modal stays visible.
I am aware that this has something to do with teh variable being set in an asynchronus function. I do not know how to make it work however and have not found a tutorial that does something similar so far.
All help appreciated.
CodePudding user response:
The problem is that login()
function is not a valid Alpine.js component. It does not return any data, so showLoginModal
is not reactive, therefore Alpine.js cannot detect when you mutate the value of the variable. A loginComponent
using Alpine.data() should look like this:
<div x-data="loginComponent()" x-show="showLoginModal" x-cloak x-transition>
<form action="/token" method="POST" @submit.prevent="submitData">
<!-- defining the login form -->
</form>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('loginComponent', () => ({
showLoginModal: true,
token: undefined,
async submitData() {
await fetch(...).then((data) => {
this.token = data.access_token
this.showLoginModal = false
})
}
}))
})
</script>
Note that we have to use the this.
prefix in the component definition to access Alpine.js data (that are reactive).