- Basic GET request getting HTML or text
- Basic GET returning JSON
- POST request
- POST form content with FormData
- POST request serialise FormData
- POST request serialise form to JSON (for minimal API request handlers)
- Uploading data as JSON
- Uploading a file
- Uploading multiple files
- Downloading a file with POST
- Download a file with GET
- Cascading/Dependent dropdown
Content Type
The default content type for a fetch request using the POST method depends on the type of data you provide in the request body:
FormDataobject:multipart/form-dataURLSearchParamsobject:application/x-www-form-urlencoded- Text string:
text/plain;charset=UTF-8 BloborBufferSource: The browser will attempt to determine the content type based on the internal data (e.g.,image/jpegfor a JPEG image).- JavaScript object: No default content type is set. You'll need to explicitly set it to
application/jsonif you intend to send JSON data.
Here's a summary of the default content types:
| Request Body Type | Default Content Type |
|---|---|
| FormData | multipart/form-data |
| URLSearchParams | application/x-www-form-urlencoded |
| String | text/plain;charset=UTF-8 |
| Blob or BufferSource | Determined based on data |
| JavaScript object | None (must be explicitly set) |
Remember:
- Always explicitly set the Content-Type header if you want to ensure a specific content type, even if the default matches your intention.
- To send JSON data, explicitly set the Content-Type header to
application/json. - To send form data, use a
FormDataobject and the default content type will be handled for you.
Basic GET request getting HTML or text
document.getElementById('load').addEventListener('click', () => {
fetch('/ajax')
.then((response) => {
// call the text() method on the response, which returns the actual text from the ReadableStream
return response.text();
})
// result represents the result of calling the text() method
.then((result) => {
document.getElementById('grid').innerHTML = result;
});
});
document.querySelector('#load').addEventListener('click', _ => {
fetch('/ajax')
.then(response => response.text())
.then(result => document.querySelector('#grid').innerHTML = result);
});
Basic GET returning json
document.getElementById('load').addEventListener('click', () => {
fetch('/ajax')
.then((response) => {
// call the json() method on the response, which parses json from the ReadableStream
return response.json();
})
// result represents the result of calling the text() method
.then((json) => {
document.getElementById('grid').innerHTML = json;
});
});
POST request
fetch(url, {
method: 'post',
headers: {
// important to set the content type - see above
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(response => response.json())
.then(data =>{
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
POST form content with FormData
let data = new FormData();
data.append('foo', 'bar');
data.append('lorem','ipsum');
fetch(url, {
method: 'post',
headers: {
// important to set the content type
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: new URLSearchParams(data).toString()
})
.then(response => response.json())
.then(data =>{
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
POST request serialise form
fetch(url, {
method: 'post',
headers: {
// important to set the content type
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: new URLSearchParams(new FormData(theFormElement)).toString()
})
.then(response => response.json())
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
POST request serialise form to JSON (for minimal API request handlers)
Note: this needs the ts compiler options set to target at least 2019
fetch(url, {
method: 'post',
headers: {
// important to set the content type to application/json
"content-type": "application/json"
},
body: JSON.stringify(Object.fromEntries(new FormData(theFormElement)))
})
.then(response => response.json())
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
Uploading JSON data
Use fetch() to POST JSON-encoded data.
const data = { username: 'example' };
fetch('https://example.com/profile', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Uploading a file
Files can be uploaded using an HTML input element, FormData() and fetch().
const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');
formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);
fetch('https://example.com/profile/avatar', {
method: 'post',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
Uploading multiple files
Files can be uploaded using an HTML input element, FormData() and fetch(). Ensure that the enctype of the form is set to multipart/form-data
const formData = new FormData();
const photos = document.querySelector('input[type="file"][multiple]');
formData.append('title', 'My Vegas Vacation');
for (let i = 0; i < photos.files.length; i++) {
formData.append(`photos_${i}`, photos.files[i]);
}
fetch('https://example.com/posts', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
Downloading a file with POST
printButton.addEventListener('click', e => {
let formData = new FormData();
formData.append('productName', selectedProductName);
formData.append('issue', selectedIssueName);
[...document.querySelectorAll('[name="entries"]:checked')].forEach(x => formData.append('selectedItems', x.value));
[...document.querySelectorAll('[name="columnoptions"]:checked')].forEach(x => formData.append('selectedColumns', x.value));
let fileName = `Running List - ${selectedProductName} ${selectedIssueName}`;
let options = {
method: 'POST',
body: new URLSearchParams(formData).toString(),
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
}
fetch('/editorialentry/runninglist', options)
.then(res => res.blob())
.then(blob => {
let a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
a.click();
});
})
Cascading/Dependent dropdown
Call loadIssues on change in principal selector. Use replaceChildren in dependent selector
const loadIssues = (id) => {
let dependentSelector = document.querySelector('#CommissionedForId');
fetch(`/api/getdata?id=${id}`).then(response => response.json()).then(items => {
let newOptions = [new Option('', '')]; // blank option first
items.forEach(item => {
newOptions.push(new Option(item.Text, item.Value));
});
dependentSelector.replaceChildren(...newOptions);
});
}
Download with GET
let fileName = '';
const allItems = [...invoiceItems].map(x => x.value);
const selectedItems = [...invoiceItems].filter(checkbox => checkbox.checked).map(x => x.value);
let qs = selectedItems.length ? selectedItems.join('&ids=') : allItems.join('&ids=');
fetch(`/invoicing?handler=invoicerequests${qs}`).then(response => {
const header = response.headers.get('Content-Disposition');
const parts = header.split(';');
fileName = parts[1].split('=')[1].replaceAll("\"", "");
return response.blob();
}).then(blob => URL.createObjectURL(blob))
.then(href => {
Object.assign(document.createElement('a'), {
href,
download: fileName,
}).click();
URL.revokeObjectURL(href);
})