Todo App (JSX)
This is a basic todo app with browser backed storage using only rvx's core features.
Note, that this example doesn't include any storage error handling or validation.
import { For, Show, Signal, sig, watch } from "rvx";
const STORAGE_KEY = "rvx-examples:todo-app";
export function Example() {
const name = sig("");
// Load items from storage by converting the
// json representation into objects with signals:
const items = sig<Item[]>([]);
try {
const json = JSON.parse(localStorage.getItem(STORAGE_KEY)!) as ItemJson[];
items.value = json.map(item => ({ name: sig(item.name), done: sig(item.done) }));
} catch (error) {
console.error(error);
}
function add() {
if (name.value) {
items.update(items => {
items.push({ name: sig(name.value), done: sig(false) });
});
name.value = "";
}
}
// Watch the json representation to save it when something changes:
watch(() => {
return items.value.map(item => ({
name: item.name.value,
done: item.done.value,
}));
}, json => {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(json));
} catch (error) {
console.error(error);
}
});
return <div class="column">
<div class="row">
<TextInput value={name} action={add} />
<button on:click={add}>Add</button>
</div>
<ul>
<For each={items}>
{item => <li class="row">
<TextInput value={item.name} />
<Show
when={item.done}
else={() => <>
<button on:click={() => { item.done.value = true }}>Done</button>
</>}
>
{() => <>
<button on:click={() => { item.done.value = false }}>Undone</button>
<button on:click={() => {
items.update(items => {
items.splice(items.indexOf(item), 1);
});
}}>Remove</button>
</>}
</Show>
</li>}
</For>
</ul>
</div>;
}
function TextInput(props: {
value: Signal<string>;
action?: () => void;
}) {
return <input
type="text"
prop:value={props.value}
on:input={event => {
props.value.value = (event.target as HTMLInputElement).value;
}}
on:keydown={event => {
if (event.key === "Enter" && props.action) {
event.preventDefault();
props.action();
}
}}
/>;
}
interface ItemJson {
name: string;
done: boolean;
}
interface Item {
name: Signal<string>;
done: Signal<boolean>;
}