A much admired feature of HTMX among beginners is it's ability to abstract away javascript and make fetch requests from the backend directly in markup.
I don't like HTMX because I think it's really limiting, I love Alpine and don't like using multiple frameworks - but I would like the ability to on occasion just do a simple request of my backend in order to populate an item in my dom from within Alpine without specifically calling a function to do that.
I have built this functionality using a simple function I have called xfetch in the below example, which is simply passed a url and returns the relevant item into the x-text, x-html or variable in x-data. It can be used in alpine as follows:
<div x-data>
<span x-text="await xfetch("url")>
</div>
I think implementing this in a straightforward way, without getting into the details of promises, etc, would be really helpful for beginners getting started with Alpine as their first JS framework.
Ideally I would make this an Alpine magic called $fetch but I can't work out how to make magics work nicely with async and await.
My current code is as follows:
<html lang="en">
<head>
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<div x-data="{ time: xfetch('http://date.jsontest.com', method = 'GET', jsonItem='time') }">
<p>
This pulls the time from an object in x-data:
<span x-text="await time"></span>
</p>
<p>
... but you can also pass a url right into the x-text:
<span x-text="await xfetch('http://date.jsontest.com', method = 'GET', jsonItem='date')"> </span>
</p>
</div>
<script>
async function xfetch(url, method='GET', jsonItem=null) {
return fetch(url, {
method: method,
})
.then((response) => response.json())
.then((responseJson) => {
return responseJson[jsonItem]
});
}
</script>
</body>
</html>
Ideally I would add in:
document.addEventListener('alpine:init', () => {
Alpine.magic('fetch', () => url => {
return await xfetch(url, method='GET', jsonItem=null)
})
})
but this doesn't work I think because the async isn't working when I put it in a $magic.
Two questions:
Thanks
EDIT: Updating this answer as @Super and I worked through this and it seems we discovered the answers to the original questions posed.
HOWEVER: it appears you cannot do both at the same time. It seems you cannot have a $magic that is async and also accepts arguments.
I would also note that HTMX has ajax functionality that handles and resolves the async Promise results for you.
For your example, perhaps try something like this
<script>
async function xfetch(url, method = 'GET', jsonItem = null) {
let response=
await fetch(url, {
method: method,
})
.then((response) => response.json())
.then((responseJson) => {
return responseJson[jsonItem]
});
return response;
}
document.addEventListener('alpine:init', async () => {
Alpine.magic('fetch', async function(url,otherdata) {
let response = await xfetch(url, method = 'GET', jsonItem = null)
return await response.text();
})
})
</script>