转载:Using Native Fetch With AlpineJs - Witty Programming
One of the most common web app patterns involves collecting data from a form and submitting it to a REST API or, the opposite, populating a form from data originating from a REST API. This pattern can easily be achieved in Alpinejs using the native javascript Fetch Api. As a bonus, I describe the fetch async version at the end of the article.
If you are not familiar with the Alpinejs, checkout my introduction article and how can help you introduce simple interactions in your web page very easily.
If you do not like using the native fetch , there is the magic helper $fetch which is using Axios behind the scenes. I prefer to use the native javascript approach to a library that adds another ~15KB payload to my build. Nowadays, with the ability to cancel the fetch , I do not see a reason not to use it. But if you like the Axios library, know that there is an Alpinejs way to it, too.
For testing purposes, we will use a free fake API powered by JSON Server and LowDB. Check these projects out cause they are amazing and may help in your endeavours. In this example, we hit the free fake API at https://jsonplaceholder.typicode.com/users/1 , which returns the following data:
We will only use the name,email, address.city, and address.street attributes from the JSON not to complicate the form structure too much.
Below you may check up the final result. We use the native JavaScript fetch in an Alpinejs component to receive data to populate the form. You may change the form data, and by clicking on the “update info” button, we are making a POST request to an API Endpoint with the updated data. The endpoint does not exist. Therefore, it returns an error, but I want to show how to use the fetch to make a post request.
Initially, let’s build our form using the tailwindcss. Tailwindcss is a utility-first CSS that let you compose your design directly in your markup. It has the same philosophy as the Alpinejs so, they often grouped together.
The best time to get our values from the REST API and display them in the form is during the alpinejs component’s initialization using the x-init attribute:
1 2 3 4 5 6 7 8 9 10 11
x-init="fetch('https://jsonplaceholder.typicode.com/users/1') .then(response=> { if (!response.ok) alert(`Something went wrong: ${response.status} - ${response.statusText}`) return response.json() }) .then(data => person = { name: data.name, email: data.email, address: data.address.street, city: data.address.city })"
We are using the fetch to hit our REST endpoint, which returns a promise. At first, we resolve the response from the endpoint and check if it was a success. If not, we alert the user about the problem. To extract the JSON data from the response object, we use the json() command, which also returns a promise that it resolves at last to a javascript object containing the data returned from the endpoint. Finally, we are populated our person object with these data.
To display the data in the form, we are binding the person object attributes to the corresponding input text boxes in our form using the x-model attribute. The x-mode attributes create a two-way binding between the input elements’ value and the value of corresponding person attributes. For example, for the name input box, we are two-way binding to the person.name :
Finally, by clicking the “UPDATE INFO” button, we are sending the form data to a REST endpoint by a POST request through the fetch command. To do that, we attach a listener to the click event using the Alpinejs event syntax @:event :
The fetch command will send a POST response to a non-existent endpoint, so the output will be an error alert. If you want to pass a header to the request, you may add it in the options object. For learning about available full options, you may check out the mozilla MDN web docs
Although, in the code above we are resolving the fetch promise through its classic approach, the async / await have achieve a very wide support on the modern browsers. So there nothing holding back to not use it (except for supporting legacy browsers). The only consideration is that alpinejs expects a function expression in its attributes instead of a function declaration. That means that we need to surround the arrow function with a self-execute function. Therefore, our x-init code is transformed:
1 2 3 4 5 6 7 8 9 10 11
x-init="(async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users/1') if (! response.ok) alert(`Something went wrong: ${response.status} - ${response.statusText}`) data = await response.json() person = { name: data.name, email: data.email, address: data.address.street, city: data.address.city } })()"
And the async / await version for the POST request code is: