atom Logo atom guides demos

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);