Skip to main content
Version: 1.0.0

Using fetch()

In YUI the jQuery functions $.ajax, $.get and $.post are often used to exchange data with server side. In YSCP, 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:

fetch(url, {headers: {accept: 'application/json'}})
HTTP Headers

With fetch() HTTP Header names can be specified in camelCase or Kebab-Case notation.

For example:

{
"Content-Type": "application/json", // Kebab-Case
contentType: "application/json" // camelCase
}

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,
{
method: 'post',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': yui.getFormToken()
}
}
)

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({foo: 'bar'});
const contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
fetch(url, {method: 'post', body, headers: {'Content-Type': contentType, 'X-CSRF-Token': yui.getFormToken()}})

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: {
'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
'X-CSRF-Token': yui.getFormToken()
},
body: new URLSearchParams({
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
);
})
.catch(error => {
this.dispatchMessage("error", error, 5000);
});
}
};
}
</script>
warning

The GraphQL API requires Craft Pro. You can start a Pro trial locally and use it however long you need to evaluate Craft—payment is only required when you start using Craft Pro on a public-facing domain.

GraphQL POST mutation request with AlpineJS

This example shows how to send a create guest cart mutation request to the YSCP 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: {
'Content-Type': "application/json;charset=utf-8",
'X-CSRF-Token': yui.getFormToken()
'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>GraphQL:</strong>
<textarea x-model="query"></textarea>
</label>
<button class="btn" @click="run" type="button">Run</button>
<template x-if="result !== ''">
<div>
<strong>Result:</strong>
<pre x-text="result"></pre>
</div>
</template>
</div>