refactor(formlist): streamline ItemsList component and clean up unused code

- Removed unused imports, including `Element`, `Node`, and `ActiveCell` struct.
- Consolidated signal management for `active_cell_position` and `active_row_index`.
- Improved focus handling by adding a reusable `handle_focus` function.
- Optimized EditableCell's event handlers for better maintainability.
This commit is contained in:
ryan 2024-12-30 16:10:13 +03:00
parent b616fbb438
commit b84cd37c44
2 changed files with 23 additions and 37 deletions

View file

@ -1,9 +1,11 @@
use leptos::*;
use leptos::logging::log;
use web_sys::FocusEvent;
#[component]
pub fn EditableCell(
value: String,
on_input: impl Fn(String) + 'static,
#[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());
@ -33,14 +35,15 @@ pub fn EditableCell(
on_input(new_value);
};
let handle_focus = move |_: web_sys::FocusEvent| {
let handle_focus = move |ev:FocusEvent| {
if is_disposed.get() {
return;
}
set_has_focus.set(true);
on_focus.call(ev);
};
let handle_blur = move |_: web_sys::FocusEvent| {
let handle_blur = move |_:FocusEvent| {
if is_disposed.get() {
return;
}

View file

@ -7,7 +7,7 @@ use leptos::logging::log;
use crate::models::item::Item;
use std::sync::{Arc, Mutex};
use wasm_bindgen::JsCast;
use web_sys::{FocusEvent, HtmlElement, Element, Node};
use web_sys::{FocusEvent, HtmlElement};
use futures_timer::Delay;
use std::time::Duration;
@ -17,11 +17,6 @@ struct WikidataSuggestion {
label: String,
description: Option<String>,
}
#[derive(Clone)]
struct ActiveCell {
row_index: usize,
position: (f64, f64),
}
#[component]
pub fn ItemsList(
@ -39,7 +34,6 @@ pub fn ItemsList(
wikidata_id: None,
}]);
let (active_cell, set_active_cell) = create_signal(None::<ActiveCell>);
let (active_cell_position, set_active_cell_position) = create_signal(None::<(f64, f64)>);
let (active_row_index, set_active_row_index) = create_signal(None::<usize>);
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(Vec::<WikidataSuggestion>::new());
@ -82,16 +76,6 @@ pub fn ItemsList(
item.name = value.clone();
fetch_wikidata_suggestions(value.clone());
set_active_row_index.set(Some(index));
// Set active cell position with validation
if let Some(element) = document().get_element_by_id(&format!("name-{}", index)) {
let rect = element.get_bounding_client_rect();
log!("Bounding rect: {:?}", rect); // Log rect details
if rect.width() > 0.0 && rect.height() > 0.0 {
set_active_cell_position.set(Some((rect.left(), rect.bottom())));
} else {
log!("Element bounding box is not valid for popup positioning.");
}
}
}
"description" => {
item.description = value.clone();
@ -114,6 +98,21 @@ pub fn ItemsList(
});
};
// Handle focus event for EditableCell
let handle_focus = move |index: usize, field: &str, event: FocusEvent| {
set_active_row_index.set(Some(index));
if field == "name" {
if let Some(target) = event.target() {
if let Some(element) = target.dyn_ref::<HtmlElement>() {
let rect = element.get_bounding_client_rect();
set_active_cell_position.set(Some((rect.left(), rect.bottom())));
}
}
} else {
set_active_cell_position.set(None);
}
};
// Add a new tag to an item
let add_tag = move |index: usize, key: String, value: String| {
set_items.update(|items| {
@ -210,35 +209,19 @@ pub fn ItemsList(
<tr>
// Editable Name Field with Wikidata Integration
<td>
<div
on:focus=move |event: FocusEvent| {
if let Some(element) = event.target().and_then(|t| t.dyn_into::<HtmlElement>().ok()) {
let rect = element.get_bounding_client_rect();
set_active_cell.set(Some(ActiveCell {
row_index: index,
position: (rect.left(), rect.top() + rect.height()),
}));
}
}
on:blur=move |_| {
spawn_local(async move {
Delay::new(Duration::from_millis(100)).await;
set_active_cell.set(None);
});
}
>
<EditableCell
value=item.name.clone()
on_input=move |value| update_item(index, "name", value)
on_focus=move |event| handle_focus(index, "name", event)
key=format!("name-{}", index)
/>
</div>
</td>
// Editable Description Field
<td>
<EditableCell
value=item.description.clone()
on_input=move |value| update_item(index, "description", value)
on_focus=move |event| handle_focus(index, "description", event)
key=format!("description-{}", index)
/>
</td>