Straightforward interactive HTTP requests from within your Alpine.JS markup.
Alpine.JS is a rugged, minimal tool for composing behavior directly in your markup. It can be used, even by those with little experience in Javascript, to add interactivity to web pages.
Alpine Fetch is a magic helper for Alpine.JS which makes it easy to do HTTP requests within markup.
One area where Alpine does require you to go outside markup is when making HTTP requests to dynamically populate parts of the page.
Someone looking to make a call on an API endpoint, might need to do something like the following:
<div x-data="{
result: null,
async retrieveData() {
this.result = await (await fetch('/endpoint')).text();
}
}"
x-init="retrieveData()"
>
<span x-text="result"></span>
</div>
... which is quite verbose, and involves promises which are not straightforward for beginners.
Alpine Fetch adds magic functions to abstract a lot of this away and makes it much more straightforward to populate your page via HTTP requests. The above example using Alpine Fetch would be:
<div x-data>
<span x-text="await $fetch('/endpoint)"></span>
</div>
Alpine Fetch can fetch simple text from the server using the $fetch
method or it can fetch and parse JSON using the $fetchjson
method.
It supports all HTTP methods such as GET
and POST
and PUT
.
It has no dependencies other than Alpine.
Include the following <script>
tag in the <head>
of your document, before Alpine:
<script defer src="https://cdn.jsdelivr.net/gh/hankhank10/alpine-fetch@main/alpine-fetch.js"></script>
At its most basic $fetch
accepts a URL and returns the contents of that URL.
Unlike the generic Javascript fetch
method which requires dealing with promises, this simply waits for the response to be received and then returns it.
$fetch
should be preceded by await
to ensure that this happens.
The most basic example is to fetch a string from the server and populate it in your markup via the x-text
method of alpine.
<div x-data>
<span x-text="await $fetch('https://expensive-crow-sarong.cyclic.cloud/hello_world')"></span>
</div>
The $fetch
helper can be used anywhere, so if you don't want to render it as text you can pass it to the x-html
method of Alpine - or to a class, or any other part of the markup. It behaves like any other variable.
<div x-data>
<span x-html="await $fetch('https://expensive-crow-sarong.cyclic.cloud/hello_world_html')"></span>
</div>
You might want to use the same data in multiple places in your markup. In that case, it would make sense to just fetch it once and use it multiple times. You can do this by retrieving it into the x-data
tag like any other variable.
<div x-data="{ hello_world: await $fetch('https://expensive-crow-sarong.cyclic.cloud/hello_world' }">
<span x-text="hello_world"></span>
<span x-text="hello_world"></span>
</div>
$fetch
retrieves data which it expects to be text, but you can also use $fetchjson
to retrieve data which is JSON and then render the relevant part of that into your page.
<div x-data>
<span x-text="await $fetchjson('https://expensive-crow-sarong.cyclic.cloud/some_json', jsonItem='weather')"></span>
</div>
$fetch
and $fetchjson
assume that you want to use a GET
method but you can specify that you want to send another.
<span x-text="await $fetch('/post_url', method='POST')"></span>
<span x-text="await $fetch('/delete_url', method='DELETE')"></span>
If you specify a DOM element or a variable to be equal to $fetch
or $fetchjson
then the methods will automatically fetch on init.
However you can also customise when they do the fetch however you like. In the below example, it will fetch only when the user clicks the button.
<div x-data="{ weather: 'uncertain at this stage' }">
The weather is <span x-text="weather"></span>
<button
x-on:click="weather = await $fetchjson('https://expensive-crow-sarong.cyclic.cloud/some_json', jsonItem='weather')"
>Click me to change the weather</button>
</div>
You can view all of these examples in the docs/index.html
file in this repo, or view a live hosted demo here.
I very much welcome comments, suggestions and contributions.
If you notice issues please open an issue on Github.
If you have improvements or suggestions please submit a pull request.