feat(example:todomvc): add editing support

- implement "onfocusout" handler
- set autofocus
- handle enter, escape and tab on a todo item
- make the `<pre>` element between todo list items of margin 0 to be unnoticable
This commit is contained in:
Sven Assmann committed 2022-01-10 14:46:23 +01:00
1 parent 02d995e3f7
commit 9849f68f25
5 files changed
+27 -10

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
html, html,
body { body, pre {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
+19 -7
View File
@@ -116,8 +116,12 @@ pub fn todo_entry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
let todo = &cx.props.todos[&cx.props.id]; let todo = &cx.props.todos[&cx.props.id];
let is_editing = use_state(&cx, || false); let is_editing = use_state(&cx, || false);
let completed = if todo.checked { "completed" } else { "" }; let completed = if todo.checked { "completed" } else { "" };
let editing = if *is_editing.get() { "editing" } else { "" };
rsx!(cx, li { class: "{completed}", rsx!(cx, li {
class: "{completed} {editing}",
onclick: move |_| is_editing.set(true),
onfocusout: move |_| is_editing.set(false),
div { class: "view", div { class: "view",
input { class: "toggle", r#type: "checkbox", id: "cbg-{todo.id}", checked: "{todo.checked}", input { class: "toggle", r#type: "checkbox", id: "cbg-{todo.id}", checked: "{todo.checked}",
onchange: move |evt| { onchange: move |evt| {
@@ -125,12 +129,20 @@ pub fn todo_entry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
} }
} }
label { r#for: "cbg-{todo.id}", pointer_events: "none", "{todo.contents}" } label { r#for: "cbg-{todo.id}", pointer_events: "none", "{todo.contents}" }
is_editing.then(|| rsx!{
input {
value: "{todo.contents}",
oninput: move |evt| cx.props.todos.modify()[&cx.props.id].contents = evt.value.clone(),
}
})
} }
is_editing.then(|| rsx!{
input {
class: "edit",
value: "{todo.contents}",
oninput: move |evt| cx.props.todos.modify()[&cx.props.id].contents = evt.value.clone(),
autofocus: "true",
onkeydown: move |evt| {
match evt.key.as_str() {
"Enter" | "Escape" | "Tab" => is_editing.set(false),
_ => {}
}
},
}
})
}) })
} }
+2 -1
View File
@@ -52,7 +52,7 @@ fn make_synthetic_event(name: &str, val: serde_json::Value) -> Arc<dyn Any + Sen
let evt = serde_json::from_value::<KeyboardData>(val).unwrap(); let evt = serde_json::from_value::<KeyboardData>(val).unwrap();
Arc::new(evt) Arc::new(evt)
} }
"focus" | "blur" => { "focus" | "blur" | "focusout" => {
// //
Arc::new(FocusData {}) Arc::new(FocusData {})
} }
@@ -117,6 +117,7 @@ fn event_name_from_typ(typ: &str) -> &'static str {
"keypress" => "keypress", "keypress" => "keypress",
"keyup" => "keyup", "keyup" => "keyup",
"focus" => "focus", "focus" => "focus",
"focusout" => "focusout",
"blur" => "blur", "blur" => "blur",
"change" => "change", "change" => "change",
"input" => "input", "input" => "input",
+4 -1
View File
@@ -91,6 +91,9 @@ pub mod on {
/// onfocus /// onfocus
onfocus onfocus
// onfocusout
onfocusout
/// onblur /// onblur
onblur onblur
]; ];
@@ -1092,7 +1095,7 @@ pub(crate) fn _event_meta(event: &UserEvent) -> (bool, EventPriority) {
"keydown" | "keypress" | "keyup" => (true, High), "keydown" | "keypress" | "keyup" => (true, High),
// Focus // Focus
"focus" | "blur" => (true, Low), "focus" | "blur" | "focusout" => (true, Low),
// Form // Form
"change" | "input" | "invalid" | "reset" | "submit" => (true, Medium), "change" | "input" | "invalid" | "reset" | "submit" => (true, Medium),
+1
View File
@@ -203,6 +203,7 @@ pub static BUILTIN_INTERNED_STRINGS: &[&'static str] = &[
"onended", "onended",
"onerror", "onerror",
"onfocus", "onfocus",
"onfocusout",
"onhashchange", "onhashchange",
"oninput", "oninput",
"oninvalid", "oninvalid",