Compare commits
2 commits
08821aaaaf
...
4f9d423a5c
Author | SHA1 | Date | |
---|---|---|---|
4f9d423a5c | |||
25195d6753 |
2 changed files with 52 additions and 18 deletions
|
@ -1,39 +1,64 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn EditableCell(
|
pub fn EditableCell(
|
||||||
value: String,
|
value: String,
|
||||||
on_input: impl Fn(String) + 'static,
|
on_input: impl Fn(String) + 'static,
|
||||||
#[prop(optional)] key: Option<String>, // Optional `key` prop
|
key: Arc<String>,
|
||||||
|
focused_cell: ReadSignal<Option<String>>,
|
||||||
|
set_focused_cell: WriteSignal<Option<String>>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let (input_value, set_input_value) = create_signal(value.clone());
|
let (input_value, set_input_value) = create_signal(value.clone());
|
||||||
let (has_focus, set_has_focus) = create_signal(false); // Track focus state locally
|
let input_ref = NodeRef::<html::Input>::new();
|
||||||
|
|
||||||
|
// Handle input event
|
||||||
let handle_input = move |e: web_sys::Event| {
|
let handle_input = move |e: web_sys::Event| {
|
||||||
let new_value = event_target_value(&e);
|
let new_value = event_target_value(&e);
|
||||||
set_input_value.set(new_value.clone());
|
set_input_value.set(new_value.clone());
|
||||||
on_input(new_value);
|
on_input(new_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle_focus = move |_: web_sys::FocusEvent| {
|
let handle_focus = {
|
||||||
set_has_focus.set(true);
|
let key = Arc::clone(&key);
|
||||||
|
move |_| {
|
||||||
|
set_focused_cell.set(Some(key.to_string()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle_blur = move |_: web_sys::FocusEvent| {
|
let handle_blur = move |_| {
|
||||||
set_has_focus.set(false);
|
set_focused_cell.set(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use key to force updates only when necessary
|
create_effect({
|
||||||
let _key = key.unwrap_or_default();
|
let key = Arc::clone(&key);
|
||||||
|
move |_| {
|
||||||
|
if let Some(ref current_key) = focused_cell.get() {
|
||||||
|
if current_key == key.as_str() {
|
||||||
|
if let Some(input) = input_ref.get() {
|
||||||
|
if web_sys::window()
|
||||||
|
.unwrap()
|
||||||
|
.document()
|
||||||
|
.unwrap()
|
||||||
|
.active_element()
|
||||||
|
.map_or(true, |el| !el.is_same_node(Some(input.as_ref())))
|
||||||
|
{
|
||||||
|
let _ = input.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={input_value.get()}
|
prop:value={input_value}
|
||||||
on:input=handle_input
|
on:input=handle_input
|
||||||
on:focus=handle_focus
|
on:focus=handle_focus
|
||||||
on:blur=handle_blur
|
on:blur=handle_blur
|
||||||
class={if has_focus.get() { "focused" } else { "not-focused" }}
|
node_ref=input_ref
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,6 +21,9 @@ pub fn ItemsList(
|
||||||
items: ReadSignal<Vec<Item>>,
|
items: ReadSignal<Vec<Item>>,
|
||||||
set_items: WriteSignal<Vec<Item>>,
|
set_items: WriteSignal<Vec<Item>>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
// State to track the currently focused cell
|
||||||
|
let (focused_cell, set_focused_cell) = create_signal(None::<String>);
|
||||||
|
|
||||||
// State to manage dynamic property names
|
// State to manage dynamic property names
|
||||||
let (custom_properties, set_custom_properties) = create_signal(Vec::<String>::new());
|
let (custom_properties, set_custom_properties) = create_signal(Vec::<String>::new());
|
||||||
|
|
||||||
|
@ -160,7 +163,9 @@ pub fn ItemsList(
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value=item.name.clone()
|
value=item.name.clone()
|
||||||
on_input=move |value| update_item(index, "name", value)
|
on_input=move |value| update_item(index, "name", value)
|
||||||
key=format!("name-{}", index)
|
key=Arc::new(format!("name-{}", index))
|
||||||
|
focused_cell=focused_cell
|
||||||
|
set_focused_cell=set_focused_cell.clone()
|
||||||
/>
|
/>
|
||||||
<ul>
|
<ul>
|
||||||
{move || {
|
{move || {
|
||||||
|
@ -200,7 +205,9 @@ pub fn ItemsList(
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value=item.description.clone()
|
value=item.description.clone()
|
||||||
on_input=move |value| update_item(index, "description", value)
|
on_input=move |value| update_item(index, "description", value)
|
||||||
key=format!("description-{}", index)
|
key=Arc::new(format!("description-{}", index))
|
||||||
|
focused_cell=focused_cell
|
||||||
|
set_focused_cell=set_focused_cell.clone()
|
||||||
/>
|
/>
|
||||||
}.into_view(),
|
}.into_view(),
|
||||||
"Tags" => view! {
|
"Tags" => view! {
|
||||||
|
@ -240,7 +247,9 @@ pub fn ItemsList(
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value=item.custom_properties.get(&property_clone).cloned().unwrap_or_default()
|
value=item.custom_properties.get(&property_clone).cloned().unwrap_or_default()
|
||||||
on_input=move |value| update_item(index, &property_clone_for_closure, value)
|
on_input=move |value| update_item(index, &property_clone_for_closure, value)
|
||||||
key=format!("custom-{}-{}", property_clone, index)
|
key=Arc::new(format!("custom-{}-{}", property_clone, index))
|
||||||
|
focused_cell=focused_cell
|
||||||
|
set_focused_cell=set_focused_cell.clone()
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue