Selectors
Basic Selector
import { LitElement, html } from "lit-element";
import { LitAtom, atom, selector } from "@klaxon/atom";
const [count, setCount] = atom({
key: 'count',
default: 0
});
const countPlusOne = selector({
key: 'countPlusOne',
get: ({getAtom}) => {
const originalCount = getAtom(count);
return originalCount + 1;
}
});
export class MyCounter extends LitAtom(LitElement) {
static atoms = [count];
static selectors = [countPlusOne];
render() {
return html`
<button @click="${() => setCount(old => old - 1)}">-</button>
<div>count: ${this.count}</div>
<div>countPlusOne: ${this.countPlusOne}</div>
<button @click="${() => setCount(old => old + 1)}">+</button>
`;
}
}
customElements.define("my-counter", MyCounter);
Nested Selectors
import { LitElement, html } from "lit-element";
import { LitAtom, atom, selector } from "@klaxon/atom";
const [count, setCount] = atom({
key: 'count',
default: 0
});
const countPlusOne = selector({
key: 'countPlusOne',
get: ({getAtom}) => {
const originalCount = getAtom(count);
return originalCount + 1;
}
});
const countPlusTen = selector({
key: 'countPlusTen',
get: async ({getSelector}) => {
const previousSelector = await getSelector(countPlusOne);
return previousSelector + 10;
}
});
export class MyCounter extends LitAtom(LitElement) {
static atoms = [count];
static atoms = [countPlusOne, countPlusTen];
render() {
return html`
<button @click="${() => setCount(old => old - 1)}">-</button>
<div>count: ${this.count}</div>
<div>countPlusOne: ${this.countPlusOne}</div>
<div>countPlusTen: ${this.countPlusTen}</div>
<button @click="${() => setCount(old => old + 1)}">+</button>
`;
}
}
customElements.define("my-counter", MyCounter);
Data fetching Selector
import { LitElement, html, css } from 'lit-element';
import { atom, selector, LitAtom } from '@klaxon/atom';
const [selected, setSelected] = atom({
key: 'selected',
default: null
});
const selectedPokemon = selector({
key: 'selectedPokemon',
get: async ({getAtom}) => {
const id = getAtom(selected);
if(id === null) return null;
return await (await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)).json();
}
});
class MyApp extends LitAtom(LitElement) {
static selectors = [selectedPokemon];
static get properties() {
return {
pokemon: { type: Array }
}
}
async connectedCallback() {
super.connectedCallback();
this.pokemon = (await (await fetch('https://pokeapi.co/api/v2/pokemon')).json()).results;
}
static styles = css`
:host {
display: flex;
flex-direction: row;
}
.pokemon {
list-style: none;
}
`
render() {
return html`
<div>
<ul class="pokemon">
<h2>Pokemon:</h2>
${this.pokemon?.map((pokemon, idx) => html`
<li>${pokemon.name} <button @click=${() => setSelected(idx+1)}>show info</button></li>
`)}
</ul>
</div>
<div>
<h2>Pokemon info:</h2>
${this.selectedPokemon
? html`
<ul>
<img alt="${this.selectedPokemon?.name}" src="${this.selectedPokemon?.sprites['front_default']}"/>
<li>name: ${this.selectedPokemon?.name}</li>
<li>height: ${this.selectedPokemon?.height}</li>
<li>weight: ${this.selectedPokemon?.weight}</li>
</ul>
`
: ''
}
</div>
`;
}
}
customElements.define('my-app', MyApp);
Data fetching Selector with loadable Atom
import { LitElement, html } from 'lit-element';
import { atom, selector, LitAtom } from '@klaxon/atom';
const [query, setQuery] = atom({
key: 'query',
loadable: async (id = 1) => {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
const body = await res.json();
return body;
}
});
const renderStatus = selector({
key: 'renderStatus',
get: ({getAtom}) => {
const { status, result } = getAtom(query);
switch(status) {
case 'success':
return html`Success! ${result.name}`
case 'error':
return html`error! :(`
case 'pending':
case 'initialized':
return html`Loading...`
}
}
});
class MyApp extends LitAtom(LitElement) {
static selectors = [renderStatus];
connectedCallback() {
super.connectedCallback();
setQuery();
}
render() {
return this.renderStatus;
}
}
customElements.define('my-app', MyApp);