Skip to content

Commit

Permalink
feat: basic TODO app; no bells, no whistles
Browse files Browse the repository at this point in the history
  • Loading branch information
jdevries3133 committed Jun 10, 2023
1 parent abf9035 commit c8373e1
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 0 deletions.
9 changes: 9 additions & 0 deletions examples/todo_app_basic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "todo_app_basic"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
leptos = { path = "../../leptos" }
14 changes: 14 additions & 0 deletions examples/todo_app_basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Basic TODO App

This is the client-side only TODO App you learned in Grade school.

## Running This Example

Just use trunk from this folder!

```bash
trunk serve --open
```

If you don't have `trunk` installed,
[click here for install instructions.](https://trunkrs.dev/)
11 changes: 11 additions & 0 deletions examples/todo_app_basic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<head>
<style>
* {
box-sizing: border-box;
font-family: Arial;
}
</style>
</head>
<body></body>
</html>
3 changes: 3 additions & 0 deletions examples/todo_app_basic/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[toolchain]
channel = "nightly"
targets = ["wasm32-unknown-unknown"]
91 changes: 91 additions & 0 deletions examples/todo_app_basic/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use leptos::*;

fn main() {
mount_to_body(|cx| view! { cx, <App /> });
}

#[derive(Eq, Hash, PartialEq, Clone, Debug)]
struct TodoItem {
id: u32,
name: String,
}

#[derive(Copy, Clone)]
struct TodoGenerator {
next_id: u32,
}

impl TodoGenerator {
fn new() -> Self {
TodoGenerator { next_id: 1 }
}
fn get_todo(&mut self, name: String) -> TodoItem {
let next_id = self.next_id;
self.next_id += 1;
TodoItem { name, id: next_id }
}
}

#[component]
fn App(cx: Scope) -> impl IntoView {
let (draft_item_name, set_draft_item_name) =
create_signal(cx, String::new());
let (todos, set_todos) = create_signal::<Vec<TodoItem>>(cx, vec![]);
let mut todo_generator = TodoGenerator::new();

let delete_todo = move |id: u32| {
set_todos.update(move |todos| {
let new_todos = todos
.iter()
.filter(|t| t.id != id)
.map(|i| i.to_owned())
.collect::<Vec<TodoItem>>();
*todos = new_todos;
});
};

view! {
cx,
<form on:submit=move |e: ev::SubmitEvent| {
e.prevent_default();
set_todos.update(|todos| {
todos.push(todo_generator.get_todo(draft_item_name()));
set_draft_item_name(String::new())
});
}>
<label for="todo-name">"Todo Name: "</label>
<input
id="todo-name"
type="text"
prop:value=draft_item_name
on:input=move |e| {
let value = event_target_value(&e);
set_draft_item_name(value);
}
/>
</form>
<For
each=todos
key=move |todo| todo.id
view=move |cx, todo| view! { cx, <TodoItem todo=todo delete_todo=Box::new(delete_todo) /> }
/>
}
}

#[component]
fn TodoItem(
cx: Scope,
todo: TodoItem,
delete_todo: Box<dyn Fn(u32)>,
) -> impl IntoView {
// Note that we could have structured our todo list as a vector of signals.
// That would be a bit noisier, but would allow us to implement inline
// editing of TODO items inside this component, where we'd recieve a signal
// here instead of a TODO item, such that we could write to that signal
// to propagate changes throughout our app!
view! {
cx,
<p>{todo.name.clone()}</p>
<button on:click=move |_| delete_todo(todo.id)>"Done"</button>
}
}

0 comments on commit c8373e1

Please sign in to comment.