Local Storage
Objeto localStorage
const name = 'value';
localStorage.setItem('name', name);
console.log(localStorage.getItem('name'));
//=> value
localStorage.setItem('person', JSON.stringify({ name: 'John' }));
console.log(JSON.parse(localStorage.getItem('name')));
//=> { name: 'John' }
const name = 'value';
localStorage.setItem('name', name);
console.log(localStorage.getItem('name'));
//=> value
localStorage.setItem('person', JSON.stringify({ name: 'John' }));
console.log(JSON.parse(localStorage.getItem('name')));
//=> { name: 'John' }
Alternativas Remotas
Monitor-app (CRUD)
Arquivos
monitor-app
├── css
│ └── style.css
├── index.html
├── js
│ ├── components
│ │ ├── HostForm.js
│ │ ├── HostTableRow.js
│ │ └── Modal.js
│ ├── data
│ │ └── seed.js
│ ├── lib
│ │ ├── dom.js
│ │ └── hosts.js
│ ├── main.js
│ └── services
│ └── storage.js
├── package-lock.json
├── package.json
└── public
└── vite.svg
Arquivos
monitor-app
├── css
│ └── style.css
├── index.html
├── js
│ ├── components
│ │ ├── HostForm.js
│ │ ├── HostTableRow.js
│ │ └── Modal.js
│ ├── data
│ │ └── seed.js
│ ├── lib
│ │ ├── dom.js
│ │ └── hosts.js
│ ├── main.js
│ └── services
│ └── storage.js
├── package-lock.json
├── package.json
└── public
└── vite.svg
Local Storage
/codes/w3c/local-storage/monitor-app/js/data/seed.js
export const hosts = [
{
id: 'e4cfb6bb-4431-42a9-b660-d5701b2f49cd',
name: 'Google DNS',
address: '8.8.8.8',
mask: '255.255.255.0',
version: 'v4',
},
{
id: 'a2bb615a-6153-41bf-8cbe-0bfb538ce511',
name: 'Google Search',
address: 'www.google.com',
mask: '255.255.255.0',
version: 'v4',
},
{
id: 'db5aecf8-aec2-4788-b59f-7e0395d5238a',
name: 'Cloudflare DNS',
address: '1.1.1.1',
mask: '255.255.255.0',
version: 'v4',
},
];
/codes/w3c/local-storage/monitor-app/js/data/seed.js
export const hosts = [
{
id: 'e4cfb6bb-4431-42a9-b660-d5701b2f49cd',
name: 'Google DNS',
address: '8.8.8.8',
mask: '255.255.255.0',
version: 'v4',
},
{
id: 'a2bb615a-6153-41bf-8cbe-0bfb538ce511',
name: 'Google Search',
address: 'www.google.com',
mask: '255.255.255.0',
version: 'v4',
},
{
id: 'db5aecf8-aec2-4788-b59f-7e0395d5238a',
name: 'Cloudflare DNS',
address: '1.1.1.1',
mask: '255.255.255.0',
version: 'v4',
},
];
/codes/w3c/local-storage/monitor-app/js/services/storage.js
import { v4 as uuidv4 } from 'uuid';
function storageInsert(key, value) {
if (typeof value === 'object') {
value = JSON.stringify(value);
}
localStorage.setItem(`@monitor-app:${key}`, value);
}
function storageSelect(key, isJSON = true) {
let value = localStorage.getItem(`@monitor-app:${key}`);
if (isJSON) {
value = JSON.parse(value);
}
return value;
}
function load(resourse, data) {
if (storageSelect('loaded', false) !== 'ok') {
storageInsert(resourse, data);
storageInsert('loaded', 'ok');
}
}
function create(resourse, value) {}
function read(resourse, id) {}
function update(resourse, id, value) {}
function remove(resourse, id) {}
export default { load, create, read, update, remove };
/codes/w3c/local-storage/monitor-app/js/services/storage.js
import { v4 as uuidv4 } from 'uuid';
function storageInsert(key, value) {
if (typeof value === 'object') {
value = JSON.stringify(value);
}
localStorage.setItem(`@monitor-app:${key}`, value);
}
function storageSelect(key, isJSON = true) {
let value = localStorage.getItem(`@monitor-app:${key}`);
if (isJSON) {
value = JSON.parse(value);
}
return value;
}
function load(resourse, data) {
if (storageSelect('loaded', false) !== 'ok') {
storageInsert(resourse, data);
storageInsert('loaded', 'ok');
}
}
function create(resourse, value) {}
function read(resourse, id) {}
function update(resourse, id, value) {}
function remove(resourse, id) {}
export default { load, create, read, update, remove };
Create a host
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function create(resource, value) {
const values = storageSelect(resource);
value = { ...value, id: uuidv4() };
storageInsert(resource, [...values, value]);
return value;
}
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function create(resource, value) {
const values = storageSelect(resource);
value = { ...value, id: uuidv4() };
storageInsert(resource, [...values, value]);
return value;
}
import Storage from './services/storage.js';
const host = {
name: 'Google DNS',
address: '8.8.8.8',
mask: '255.255.255.0',
version: 'v4',
};
Storage.create('hosts', host);
import Storage from './services/storage.js';
const host = {
name: 'Google DNS',
address: '8.8.8.8',
mask: '255.255.255.0',
version: 'v4',
};
Storage.create('hosts', host);
Read hosts
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function read(resourse, id) {
const values = storageSelect(resourse);
if (id) {
return values.find((value) => value.id === id);
} else {
return values;
}
}
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function read(resourse, id) {
const values = storageSelect(resourse);
if (id) {
return values.find((value) => value.id === id);
} else {
return values;
}
}
import Storage from './services/storage.js';
Storage.read('hosts');
Storage.read('hosts', 1);
import Storage from './services/storage.js';
Storage.read('hosts');
Storage.read('hosts', 1);
Update a host
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function update(resourse, id, value) {
const values = storageSelect(resourse);
const index = values.findIndex((value) => value.id === id);
if (index >= 0) {
value = { id, ...value };
values[index] = {...values[index], ...value};
storageInsert(resourse, values);
return value;
} else {
return false;
}
}
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function update(resourse, id, value) {
const values = storageSelect(resourse);
const index = values.findIndex((value) => value.id === id);
if (index >= 0) {
value = { id, ...value };
values[index] = {...values[index], ...value};
storageInsert(resourse, values);
return value;
} else {
return false;
}
}
import Storage from './services/storage.js';
Storage.update('hosts', { id: 1, value: 15000 });
import Storage from './services/storage.js';
Storage.update('hosts', { id: 1, value: 15000 });
Delete a host
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function remove(resourse, id) {
const values = storageSelect(resourse);
const index = values.findIndex((value) => value.id === id);
if (index >= 0) {
values.splice(index, 1);
}
storageInsert(resourse, values);
}
/codes/w3c/local-storage/monitor-app/js/services/storage.js
function remove(resourse, id) {
const values = storageSelect(resourse);
const index = values.findIndex((value) => value.id === id);
if (index >= 0) {
values.splice(index, 1);
}
storageInsert(resourse, values);
}
import Storage from './services/storage.js';
Storage.remove('hosts', 1);
import Storage from './services/storage.js';
Storage.remove('hosts', 1);
Front-end
$ npm i uuidv4 iconify-icon bootstrap
$ npm i uuidv4 iconify-icon bootstrap
/codes/w3c/local-storage/monitor-app/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Monitor App</title>
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1 class="text-center m-0 p-5">Monitor App</h1>
<div class="card table-hosts">
<div class="card-header">
<h5 class="text-center">
Hosts
<div
class="float-end create-host-event lh-base"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:plus"></iconify-icon>
</div>
</h5>
</div>
<div class="card-body">
<table class="table table-hosts">
<thead>
<tr>
<th>Nome</th>
<th>Endereço</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<script type="module" src="/js/main.js"></script>
</body>
</html>
/codes/w3c/local-storage/monitor-app/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Monitor App</title>
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1 class="text-center m-0 p-5">Monitor App</h1>
<div class="card table-hosts">
<div class="card-header">
<h5 class="text-center">
Hosts
<div
class="float-end create-host-event lh-base"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:plus"></iconify-icon>
</div>
</h5>
</div>
<div class="card-body">
<table class="table table-hosts">
<thead>
<tr>
<th>Nome</th>
<th>Endereço</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<script type="module" src="/js/main.js"></script>
</body>
</html>
/codes/w3c/local-storage/monitor-app/js/main.js
import 'bootstrap';
import 'iconify-icon';
import HostForm from './components/HostForm';
import Modal from './components/Modal';
import Hosts from './lib/hosts';
import Storage from './services/storage';
import { hosts } from './data/seed';
import 'bootstrap/dist/css/bootstrap.css';
import '../css/style.css';
Storage.load('hosts', hosts);
Hosts.load();
HostForm.create();
Modal.create();
/codes/w3c/local-storage/monitor-app/js/main.js
import 'bootstrap';
import 'iconify-icon';
import HostForm from './components/HostForm';
import Modal from './components/Modal';
import Hosts from './lib/hosts';
import Storage from './services/storage';
import { hosts } from './data/seed';
import 'bootstrap/dist/css/bootstrap.css';
import '../css/style.css';
Storage.load('hosts', hosts);
Hosts.load();
HostForm.create();
Modal.create();
/codes/w3c/local-storage/monitor-app/css/style.css
iconify-icon:hover {
cursor: pointer;
}
/codes/w3c/local-storage/monitor-app/css/style.css
iconify-icon:hover {
cursor: pointer;
}
Utilitários
/codes/w3c/local-storage/monitor-app/js/lib/dom.js
export const $ = (selector) => document.querySelector(selector);
/codes/w3c/local-storage/monitor-app/js/lib/dom.js
export const $ = (selector) => document.querySelector(selector);
/codes/w3c/local-storage/monitor-app/js/lib/hosts.js
import * as HostTableRow from '../components/HostTableRow';
import Storage from '../services/storage';
function load() {
const hosts = Storage.read('hosts');
hosts.forEach(HostTableRow.create);
}
function create(investment) {
delete investment.id;
const createdInvestment = Storage.create('hosts', investment);
HostTableRow.create(createdInvestment);
}
function update(investment) {
const { id } = investment;
const updatedInvestment = Storage.update('hosts', id, investment);
HostTableRow.update(updatedInvestment);
}
function remove(investment) {
const { id } = investment;
Storage.remove('hosts', id);
HostTableRow.remove(id);
}
export default { load, create, update, remove };
/codes/w3c/local-storage/monitor-app/js/lib/hosts.js
import * as HostTableRow from '../components/HostTableRow';
import Storage from '../services/storage';
function load() {
const hosts = Storage.read('hosts');
hosts.forEach(HostTableRow.create);
}
function create(investment) {
delete investment.id;
const createdInvestment = Storage.create('hosts', investment);
HostTableRow.create(createdInvestment);
}
function update(investment) {
const { id } = investment;
const updatedInvestment = Storage.update('hosts', id, investment);
HostTableRow.update(updatedInvestment);
}
function remove(investment) {
const { id } = investment;
Storage.remove('hosts', id);
HostTableRow.remove(id);
}
export default { load, create, update, remove };
Componentes
/codes/w3c/local-storage/monitor-app/js/components/HostTableRow.js
import { $ } from '../lib/dom';
import Hosts from '../lib/hosts';
import HostForm from './HostForm';
export function create(host) {
const row = `
<tr id="host-${host.id}">
<td class="host-name">
${host.name}
</td>
<td class="host-address">
${host.address}
</td>
<td class="host-events">
<span
class="icon-pencil"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:edit"></iconify-icon>
</span>
<span class="icon-trash" data-bs-toggle="modal" data-bs-target="#modal">
<iconify-icon class="ms-4" icon="bx:trash"></iconify-icon>
</span>
</td>
</tr>
`;
$('.table-hosts tbody').insertAdjacentHTML('beforeend', row);
$(`#host-${host.id} .icon-pencil`).onclick = () => {
HostForm.setTitleForm('Atualizar Host');
HostForm.setValues(host);
HostForm.handleSubmit((host) => Hosts.update(host));
};
$(`#host-${host.id} .icon-trash`).onclick = () => {
$(`.modal .host-name`).innerText = host.name;
$(`.modal .remove-host-btn`).onclick = () => Hosts.remove(host);
};
}
export function update({ id, name, address }) {
$(`#host-${id} .host-name`).innerText = name;
$(`#host-${id} .host-address`).innerText = address;
}
export function remove(id) {
$(`#host-${id}`).remove();
}
/codes/w3c/local-storage/monitor-app/js/components/HostTableRow.js
import { $ } from '../lib/dom';
import Hosts from '../lib/hosts';
import HostForm from './HostForm';
export function create(host) {
const row = `
<tr id="host-${host.id}">
<td class="host-name">
${host.name}
</td>
<td class="host-address">
${host.address}
</td>
<td class="host-events">
<span
class="icon-pencil"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:edit"></iconify-icon>
</span>
<span class="icon-trash" data-bs-toggle="modal" data-bs-target="#modal">
<iconify-icon class="ms-4" icon="bx:trash"></iconify-icon>
</span>
</td>
</tr>
`;
$('.table-hosts tbody').insertAdjacentHTML('beforeend', row);
$(`#host-${host.id} .icon-pencil`).onclick = () => {
HostForm.setTitleForm('Atualizar Host');
HostForm.setValues(host);
HostForm.handleSubmit((host) => Hosts.update(host));
};
$(`#host-${host.id} .icon-trash`).onclick = () => {
$(`.modal .host-name`).innerText = host.name;
$(`.modal .remove-host-btn`).onclick = () => Hosts.remove(host);
};
}
export function update({ id, name, address }) {
$(`#host-${id} .host-name`).innerText = name;
$(`#host-${id} .host-address`).innerText = address;
}
export function remove(id) {
$(`#host-${id}`).remove();
}
/codes/w3c/local-storage/monitor-app/js/components/HostForm.js
import { $ } from '../lib/dom';
import Hosts from '../lib/hosts';
export function setValues({ id, name, address }) {
const form = $('form');
form.id.value = id;
form.name.value = name;
form.address.value = address;
}
export function getValues() {
const form = $('form');
const host = Object.fromEntries(new FormData(form));
return host;
}
export function setTitleForm(title) {
$('.offcanvas-title').innerText = title;
}
export function create() {
const form = `
<div
class="offcanvas offcanvas-end"
tabindex="-1"
id="offcanvasRight"
aria-labelledby="offcanvasRightLabel"
>
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasRightLabel"></h5>
<button
type="button"
id="close-offcanvas"
class="btn-close"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div>
<div class="offcanvas-body">
<form>
<input
type="hidden"
id="id"
name="id"
>
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input
type="text"
class="form-control"
id="name"
name="name"
placeholder="Google Search"
/>
</div>
<div class="mb-3">
<label for="address" class="form-label">Endereço</label>
<input
type="text"
class="form-control"
id="address"
name="address"
placeholder="www.google.com"
/>
</div>
<div>
<button
type="submit"
class="btn btn-secondary"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
Salvar
</button>
</div>
</form>
</div>
</div>
`;
$('body > .container').insertAdjacentHTML('afterend', form);
$('.create-host-event').onclick = () => {
const form = $('form');
setTitleForm('Cadastro de Host');
form.reset();
handleSubmit(Hosts.create);
};
}
function handleSubmit(callback) {
const form = $('form');
form.onsubmit = async (event) => {
event.preventDefault();
const host = getValues();
callback(host);
form.reset();
};
}
export default { setValues, getValues, setTitleForm, create, handleSubmit };
/codes/w3c/local-storage/monitor-app/js/components/HostForm.js
import { $ } from '../lib/dom';
import Hosts from '../lib/hosts';
export function setValues({ id, name, address }) {
const form = $('form');
form.id.value = id;
form.name.value = name;
form.address.value = address;
}
export function getValues() {
const form = $('form');
const host = Object.fromEntries(new FormData(form));
return host;
}
export function setTitleForm(title) {
$('.offcanvas-title').innerText = title;
}
export function create() {
const form = `
<div
class="offcanvas offcanvas-end"
tabindex="-1"
id="offcanvasRight"
aria-labelledby="offcanvasRightLabel"
>
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasRightLabel"></h5>
<button
type="button"
id="close-offcanvas"
class="btn-close"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div>
<div class="offcanvas-body">
<form>
<input
type="hidden"
id="id"
name="id"
>
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input
type="text"
class="form-control"
id="name"
name="name"
placeholder="Google Search"
/>
</div>
<div class="mb-3">
<label for="address" class="form-label">Endereço</label>
<input
type="text"
class="form-control"
id="address"
name="address"
placeholder="www.google.com"
/>
</div>
<div>
<button
type="submit"
class="btn btn-secondary"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
Salvar
</button>
</div>
</form>
</div>
</div>
`;
$('body > .container').insertAdjacentHTML('afterend', form);
$('.create-host-event').onclick = () => {
const form = $('form');
setTitleForm('Cadastro de Host');
form.reset();
handleSubmit(Hosts.create);
};
}
function handleSubmit(callback) {
const form = $('form');
form.onsubmit = async (event) => {
event.preventDefault();
const host = getValues();
callback(host);
form.reset();
};
}
export default { setValues, getValues, setTitleForm, create, handleSubmit };
/codes/w3c/local-storage/monitor-app/js/components/Modal.js
import { $ } from '../lib/dom';
function create() {
const modal = `
<div class="modal fade" id="modal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="modalLabel">Remover host</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Deseja remover o host <span class="host-name fw-bold"></span>?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary remove-host-btn" data-bs-dismiss="modal">Confirmar</button>
</div>
</div>
</div>
</div>
`;
$('body > .container').insertAdjacentHTML('afterend', modal);
}
export default { create };
/codes/w3c/local-storage/monitor-app/js/components/Modal.js
import { $ } from '../lib/dom';
function create() {
const modal = `
<div class="modal fade" id="modal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="modalLabel">Remover host</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Deseja remover o host <span class="host-name fw-bold"></span>?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary remove-host-btn" data-bs-dismiss="modal">Confirmar</button>
</div>
</div>
</div>
</div>
`;
$('body > .container').insertAdjacentHTML('afterend', modal);
}
export default { create };