<div class="container mt-3">
<header class="clearfix">
<h1 class='d-inline-block'>Fetch Example</h1>
<a href="https://time2hack.com/2017/11/goodbye-xmlhttprequest-ajax-with-fetch-api-demo/" target="_blank" class="btn btn-info float-right">Read full post</a>
</header>
<hr/>
<div class="row">
<div class="col-sm-8">
<div class="row">
<div class="col-sm-12" data-param="false">
<div class="form-group">
<label for="endpoint">Endpoint</label>
<input type="text" value="https://jsonplaceholder.typicode.com/posts" class="form-control" id="endpoint" >
</div>
</div>
<div data-param="true" class="col-sm-12 d-none">
<div class="row">
<div class="col-sm-9">
<div class="form-group">
<label for="endpoint">Endpoint</label>
<input type="text" readonly value="https://jsonplaceholder.typicode.com/posts" class="form-control" id="endpoint" >
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<label for="param">Param (postId)</label>
<input type="text" readonly value="10" class="form-control" id="param" >
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<label for="method">Method</label>
<select class="form-control" id="method">
<option value="GET">GET</option>
<option value="POST" data-body selected>POST</option>
<option value="PUT" data-body data-param>PUT</option>
<option value="DELETE" data-param>DELETE</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6"></div>
<div class="col-md-6"></div>
</div>
<div class="form-group fields-group">
<label >Fields: <button type="button" id="add" class="btn btn-info btn-sm">Add Field</button></label>
<table id="fields" class="table table-bordered table-sm">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" class="form-control key" placeholder="Key"></td>
<td><input type="text" class="form-control value" placeholder="Value" /></td>
<td>
<button type="button" class="btn btn-outline-danger remove">Remove</button>
</td>
</tr>
</tbody>
</table>
<small class="form-text text-muted">Empty keys won't be sent</small>
</div>
<div>
<button type="button" class="btn btn-outline-primary btn-lg" id="send">Send</button>
<span class="d-none" id="status">
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M19,8L15,12H18A6,6 0 0,1 12,18C11,18 10.03,17.75 9.2,17.3L7.74,18.76C8.97,19.54 10.43,20 12,20A8,8 0 0,0 20,12H23M6,12A6,6 0 0,1 12,6C13,6 13.97,6.25 14.8,6.7L16.26,5.24C15.03,4.46 13.57,4 12,4A8,8 0 0,0 4,12H1L5,16L9,12"></path>
</svg>
</span>
</div>
<hr/>
<div class="response">
<div class="row">
<div class="col-sm-8">
<h4>Response:</h4>
<pre id="result" class="border border-primary rounded"></pre>
</div>
<div class="col-sm-4">
<h4>Request:</h4>
<pre id="request" class="border border-primary rounded"></pre>
</div>
</div>
</div>
</div>
#result, #request {
padding: 10px;
max-height: 500px;
overflow: auto;
}
header {
padding-top: 10px;
}
#status svg{
animation: spin infinite 2s linear;
}
@keyframes spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
const input = name => `<input type="text"
class="form-control ${name.toLowerCase()}" placeholder="${name}" />`;
const fieldTpl = data => `
<tr>
<td>${input("Key")}</td>
<td>${input("Value")}</td>
<td><button type="button" class="btn btn-outline-danger remove">Remove</button></td>
</tr>
`;
document.querySelector("#add").addEventListener("click", e => {
$append(fieldTpl(), document.querySelector("#fields tbody"));
});
document.querySelector("#method").addEventListener("change", e => {
const val = document.querySelector("#method").value;
const option = document.querySelector(`#method option[value="${val}"]`);
const param = option.dataset.param !== undefined;
document
.querySelector(".fields-group")
.classList[option.dataset.body === undefined ? "add" : "remove"]("d-none");
console.log(param, document.querySelector(`[data-param='${param}']`));
document.querySelector(`[data-param='${param}']`).classList.remove('d-none')
document.querySelector(`[data-param='${!param}']`).classList.add('d-none')
});
document.querySelector("#fields").addEventListener("click", e => {
if (e.target.classList.contains("remove")) {
e.target.parentElement.parentElement.remove();
}
});
const getKeyValues = () => {
const keys = document.querySelectorAll('.key');
const values = document.querySelectorAll('.value');
let obj = {};
keys.forEach((key, index) => {
if(key.value !== '') {
obj[key.value] = values[index].value;
}
});
return obj;
}
document.querySelector("#send").addEventListener("click", e => {
document.querySelector("#send").classList.add('d-none')
document.querySelector("#status").classList.remove('d-none')
const suffix = {
GET: '',
POST: '',
PUT: '/10',
DELETE: '/10',
};
const method = document.querySelector("#method").value;
const url = `https://jsonplaceholder.typicode.com/posts${suffix[method]}`;
let reqConf = {method};
if(method === 'POST' || method === 'PUT') {
const headers = new Headers();
headers.append("Content-Type", "application/json");
let body = getKeyValues();
reqConf = Object.assign({}, {
headers,
body: JSON.stringify(body),
}, reqConf);
}
const request = new Request(url, reqConf)
document.querySelector('#request').innerHTML = JSON.stringify(request, replacer, 2);
fetch(request)
.then(response => response.json())
.then(data => {
document.querySelector("#send").classList.remove('d-none')
document.querySelector("#status").classList.add('d-none')
document.querySelector('#result').innerHTML = JSON.stringify(data, replacer, 2);
});
});
const $append = (markup, parent) => {
const temp_container = document.createElement('tbody');
temp_container.innerHTML = markup;
while (temp_container.firstChild) {
parent.appendChild(temp_container.firstChild);
}
};
function replacer(key, value) {
// Filtering out properties
if (value instanceof Request) {
return ['method', 'url', 'headers', 'referrer', 'mode', 'body'].reduce((acc, key) => {
acc[key] = replacer(key, value[key]);
return acc;
}, {});
}
if (value instanceof Headers) {
const i = value.entries();
const ret = {};
let v = i.next();
while(!v.done) {
ret[v.value[0]] = v.value[1]
v = i.next();
}
return ret;
}
return value;
}
View Compiled
This Pen doesn't use any external JavaScript resources.