fix(editable cells): enhance EditableCell component with editing toggle and Rc for on_input
- Replaced `on_input` function with `Rc<dyn Fn(String)>` to enable cloning and safe usage in closures. - Introduced `is_editing` signal to manage toggling between display and input modes. - Added a persistent default key reference to avoid unnecessary updates. - Improved focus and blur handling for better state management. - Wrapped input and display logic in a dynamic `cell_view` function for cleaner separation.
This commit is contained in:
parent
b84cd37c44
commit
a02fcabe19
2 changed files with 39 additions and 14 deletions
|
@ -1,17 +1,22 @@
|
|||
use leptos::*;
|
||||
use leptos::logging::log;
|
||||
use std::rc::Rc;
|
||||
use web_sys::FocusEvent;
|
||||
#[component]
|
||||
pub fn EditableCell(
|
||||
value: String,
|
||||
on_input: impl Fn(String) + 'static,
|
||||
on_input: Rc<dyn Fn(String)>, // Use `Rc` to allow cloning
|
||||
#[prop(into)] on_focus: Callback<FocusEvent>,
|
||||
#[prop(optional)] key: Option<String>, // Optional `key` prop
|
||||
) -> impl IntoView {
|
||||
let (input_value, set_input_value) = create_signal(value.clone());
|
||||
let (has_focus, set_has_focus) = create_signal(false); // Track focus state locally
|
||||
|
||||
let (is_disposed, set_disposed) = create_signal(false); // Track disposal state
|
||||
let (is_editing, set_is_editing) = create_signal(false);
|
||||
|
||||
// persistent default key value
|
||||
let default_key = String::new();
|
||||
let key_ref = key.as_ref().unwrap_or(&default_key);
|
||||
|
||||
// Ensure signals aren't updated after disposal
|
||||
on_cleanup(move || {
|
||||
|
@ -26,6 +31,7 @@ pub fn EditableCell(
|
|||
};
|
||||
|
||||
let handle_input = move |e: web_sys::Event| {
|
||||
let on_input = Rc::clone(&on_input); // Clone `on_input` to use inside the closure
|
||||
log_signal_get("input_value");
|
||||
if is_disposed.get_untracked() {
|
||||
return;
|
||||
|
@ -39,6 +45,7 @@ pub fn EditableCell(
|
|||
if is_disposed.get() {
|
||||
return;
|
||||
}
|
||||
set_is_editing.set(true);
|
||||
set_has_focus.set(true);
|
||||
on_focus.call(ev);
|
||||
};
|
||||
|
@ -47,20 +54,37 @@ pub fn EditableCell(
|
|||
if is_disposed.get() {
|
||||
return;
|
||||
}
|
||||
set_is_editing.set(false);
|
||||
set_has_focus.set(false);
|
||||
};
|
||||
|
||||
// Use key to force updates only when necessary
|
||||
let _key = key.unwrap_or_default();
|
||||
let cell_view = move || {
|
||||
if is_editing.get() {
|
||||
view! {
|
||||
<input
|
||||
type="text"
|
||||
value={input_value.get()}
|
||||
on:input=handle_input.clone()
|
||||
on:focus=handle_focus.clone()
|
||||
on:blur=handle_blur.clone()
|
||||
class={if has_focus.get() { "focused" } else { "not-focused" }}
|
||||
/>
|
||||
}.into_view()
|
||||
} else {
|
||||
view! {
|
||||
<div
|
||||
tabindex="0"
|
||||
on:focus=handle_focus.clone()
|
||||
>
|
||||
{input_value.get()}
|
||||
</div>
|
||||
}.into_view()
|
||||
}
|
||||
};
|
||||
|
||||
view! {
|
||||
<input
|
||||
type="text"
|
||||
value={input_value.get()}
|
||||
on:input=handle_input
|
||||
on:focus=handle_focus
|
||||
on:blur=handle_blur
|
||||
class={if has_focus.get() { "focused" } else { "not-focused" }}
|
||||
/>
|
||||
<div key={key_ref.clone()}>
|
||||
{cell_view}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use wasm_bindgen::JsCast;
|
|||
use web_sys::{FocusEvent, HtmlElement};
|
||||
use futures_timer::Delay;
|
||||
use std::time::Duration;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
struct WikidataSuggestion {
|
||||
|
@ -211,7 +212,7 @@ pub fn ItemsList(
|
|||
<td>
|
||||
<EditableCell
|
||||
value=item.name.clone()
|
||||
on_input=move |value| update_item(index, "name", value)
|
||||
on_input=Rc::new(move |value| update_item(index, "name", value))
|
||||
on_focus=move |event| handle_focus(index, "name", event)
|
||||
key=format!("name-{}", index)
|
||||
/>
|
||||
|
@ -220,7 +221,7 @@ pub fn ItemsList(
|
|||
<td>
|
||||
<EditableCell
|
||||
value=item.description.clone()
|
||||
on_input=move |value| update_item(index, "description", value)
|
||||
on_input=Rc::new(move |value| update_item(index, "description", value))
|
||||
on_focus=move |event| handle_focus(index, "description", event)
|
||||
key=format!("description-{}", index)
|
||||
/>
|
||||
|
|
Loading…
Add table
Reference in a new issue