Using fetch()
In Luma the jQuery functions $.ajax
, $.get
and $.post
are often used to exchange data with server side Magento. In Hyvä, the native browser function window.fetch
is used instead.
fetch()
is well documented, but here are some simple examples for reference or to get you started.
A simple fetch GET request
A simple request to a controller returning JSON content might look like like this:
fetch(url)
.then(response => {
if (! response.ok) console.warn('GET request failed');
return response.json()
})
.then(data => {
// do something with `data`
})
.catch(error => {
// optionally catch errors and display them
})
.finally(() => {
// optionally run some code that is always executed when done.
// for example, hiding a loading indicator
})
As quick reminder, GET requests do not have request bodies, so any parameters need to be added to the requested URL before calling fetch.
The response
object has many other properties and methods. Please refer to the browser API documentation for details.
Sending an Accept header
If we need to tell the server we expect a JSON response, we can pass an Accept header:
HTTP Headers
With fetch()
HTTP Header names can be specified in camelCase
or 'Kebab-Case'
notation.
For example:
A simple Ajax POST fetch request with JSON data
For POST requests we can specify a request body.
Because we send a body, we also need to set the Content-Type
header.
fetch(
url + '?form_key=' + hyva.getFormKey(),
{
method: 'post',
body: JSON.stringify(data),
headers: {contentType: 'application/json'}
}
)
A simple Ajax form POST request
In this example the form key is added as a parameter to the POST body.
const body = new URLSearchParams({form_key: hyva.getFormKey(), foo: 'bar'});
const contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
fetch(url, {method: 'post', body, headers: {'Content-Type': contentType}})
Simulating a XMLHttpRequest Ajax request with fetch
This example uses the fetch API to simulate an Ajax request with the XMLHttpRequest object.
<script>
function doAjaxCall(sections) {
fetch(`${BASE_URL}path/to/ajax/call`, {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest",
},
})
.then(response => {
if (response.ok) {
return response.json();
} else {
console.warn("GET request failed", response);
}
})
.then(data => {
if (data) {
//do something
}
});
}
window.addEventListener("load", doAjaxCall);
</script>
Form Ajax POST Ajax request with AlpineJS
This example showcases an Ajax POST request that is triggered from Alpine.js.
The result is displayed in a message.
<div x-data="initSomeComponent()">
<button @click="doPostRequest(1)">Do POST</button>
</div>
<script>
function initSomeComponent() {
return {
dispatchMessage(type, message, timeout) {
typeof window.dispatchMessages && window.dispatchMessages(
[{
type: type,
text: message,
}],
timeout
);
},
doPostRequest(someId) {
const postUrl = `${BASE_URL}path/to/ajax/call/`;
fetch(postUrl, {
headers: {
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
},
body: new URLSearchParams({
form_key: hyva.getFormKey(),
someId: someId,
uenc: btoa(window.location.href)
}),
method: "POST",
mode: "cors",
credentials: "include",
})
.then(response => {
if (response.redirected) {
window.location.href = response.url;
} else if (response.ok) {
return response.json();
} else {
this.dispatchMessage("warning", "Post request failed", 5000);
}
})
.then(response => {
if (!response) {
return;
}
this.dispatchMessage(
response.success ? "success" : "error",
response.success
? "Post request was successful."
: response.error_message,
5000
);
// uncomment to reload customer section data
/*
const reloadCustomerDataEvent = new CustomEvent(
"reload-customer-section-data"
);
window.dispatchEvent(reloadCustomerDataEvent);
*/
})
.catch(error => {
this.dispatchMessage("error", error, 5000);
});
}
};
}
</script>
GraphQL POST mutation request with AlpineJS
This example shows how to send a create guest cart mutation request to the Magento GraphQL API with fetch.
<div x-data="initSomeComponent()">
<button @click="doGQLPostRequest(1)">Create guest cart</button>
<div>
Guest cart id: <span x-text="guestCartId || 'not set yet'"></span>
</div>
</div>
<script>
function initSomeComponent() {
return {
guestCartId: "",
createGuestCartQuery: `mutation {
createEmptyCart
}`,
doGQLPostRequest() {
fetch(BASE_URL + "graphql", {
method: "POST",
headers: {
contentType: "application/json;charset=utf-8",
store: "default",
},
body: JSON.stringify({ query: this.createGuestCartQuery }),
})
.then(response => response.json())
.then(data => {
this.guestCartId = (data && data.data && data.data.createEmptyCart) || "";
});
},
};
}
</script>
GraphQL GET query request with AlpineJS
This example shows how to send a GraphQL query with a GET request
<script>
function graphqlViewModelTest() {
return {
result: '',
query: `{
products(
filter: {
name: {
match: "Tank"
}
}
pageSize: 1
) {
total_count
items {
name
small_image {
url
label
}
}
}
}`,
run() {
this.result = 'Loading...';
window.fetch('/graphql?' + new URLSearchParams({query: this.query}))
.then(response => response.json())
.then(result => {
this.result = result.errors && result.errors.length > 0
? result.errors.map(e => e.message).join("n")
: JSON.stringify(result.data, null, 2);
});
}
};
}
</script>
<div x-data="graphqlViewModelTest()">
<label><strong>GrahpQL:</strong>
<textarea x-model="query" class="w-full h-80"></textarea>
</label>
<button class="btn" @click="run">Run</button>
<template x-if="result !== ''">
<div class="mt-4">
<strong>Result:</strong>
<pre x-text="result"></pre>
</div>
</template>
</div>