fix(items_list): attempt to resolve Bloodhound typeahead reinitialization issue

- Simplified the JavaScript code in the on_focus callback to ensure proper execution
- Added direct DOM manipulation in the on_input callback to force events to trigger
- Added explicit reinitialization of Bloodhound when an input receives focus
- Used a timeout to ensure DOM updates have time to propagate before triggering events
This commit is contained in:
ryan 2025-06-04 16:24:11 +03:00
parent 8799d5c144
commit 7064520b21

View file

@ -375,32 +375,38 @@ pub fn ItemsList(
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(HashMap::<String, Vec<WikidataSuggestion>>::new()); let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(HashMap::<String, Vec<WikidataSuggestion>>::new());
// Function to fetch Wikidata suggestions // Function to fetch Wikidata suggestions
let fetch_wikidata_suggestions = move |key: String, query: String| { let fetch_wikidata_suggestions = {
log!("Fetching suggestions for key: {}, query: {}", key, query); let set_wikidata_suggestions = set_wikidata_suggestions.clone();
spawn_local(async move {
if query.is_empty() { move |key: String, query: String| {
set_wikidata_suggestions.update(|suggestions| { log!("Fetching suggestions for key: {}, query: {}", key, query);
suggestions.remove(&key); let set_wikidata_suggestions_clone = set_wikidata_suggestions.clone();
});
return;
}
let url = format!( spawn_local(async move {
"https://www.wikidata.org/w/api.php?action=wbsearchentities&search={}&language=en&limit=5&format=json&origin=*", if query.is_empty() {
query set_wikidata_suggestions_clone.update(|suggestions| {
); suggestions.remove(&key);
});
match gloo_net::http::Request::get(&url).send().await { return;
Ok(response) => {
if let Ok(data) = response.json::<WikidataResponse>().await {
set_wikidata_suggestions.update(|suggestions| {
suggestions.insert(key, data.search);
});
}
} }
Err(_) => log!("Failed to fetch Wikidata suggestions"),
} let url = format!(
}); "https://www.wikidata.org/w/api.php?action=wbsearchentities&search={}&language=en&limit=5&format=json&origin=*",
query
);
match gloo_net::http::Request::get(&url).send().await {
Ok(response) => {
if let Ok(data) = response.json::<WikidataResponse>().await {
set_wikidata_suggestions_clone.update(|suggestions| {
suggestions.insert(key, data.search);
});
}
}
Err(_) => log!("Failed to fetch Wikidata suggestions"),
}
});
}
}; };
//function to fetch properties //function to fetch properties
@ -1027,70 +1033,89 @@ pub fn ItemsList(
}) })
is_last_row={index == items.len() - 1} is_last_row={index == items.len() - 1}
on_input=Callback::new({ on_input=Callback::new({
let item_id = item.id.clone();
let input_id = format!("name-input-{}-{}", index, item.id);
let key = format!("name-{}-{}", index, item.id);
// Create a direct reference to fetch_wikidata_suggestions
let fetch_wikidata_suggestions_clone = fetch_wikidata_suggestions.clone();
move |value: String| { move |value: String| {
// Input handling logic // Trigger the Rust-side fetch
fetch_wikidata_suggestions_clone(key.clone(), value.clone());
// Force Bloodhound to update
let js_code = format!(
r#"
try {{
// Get the input element
const inputElement = document.getElementById("{}");
if (!inputElement) {{
console.error("[RUST] Input element not found:", "{}");
return;
}}
// Set the value and trigger an input event
inputElement.value = "{}";
const event = new Event("input", {{ bubbles: true }});
inputElement.dispatchEvent(event);
console.log("[RUST] Triggered input event for {} with value: {}", "{}", "{}");
}} catch (e) {{
console.error("[RUST] Error triggering input event:", e);
}}
"#,
input_id, input_id,
value,
input_id, value, input_id, value
);
// Execute the JavaScript
let _ = js_sys::eval(&js_code);
} }
}) })
on_focus=Callback::new({ on_focus=Callback::new({
// Update the focused item ID when input receives focus
let item_id = item.id.clone(); let item_id = item.id.clone();
let set_focused_item_id = set_focused_item_id.clone(); let set_focused_item_id = set_focused_item_id.clone();
let input_id = format!("name-input-{}-{}", index, item.id); let input_id = format!("name-input-{}-{}", index, item.id);
move |_| { move |_| {
log!("Name input focused: item_id={}", item_id); log!("Name input focused: item_id={}", item_id);
set_focused_item_id.set(Some(item_id.clone())); set_focused_item_id.set(Some(item_id.clone()));
// Force Bloodhound to initialize/reinitialize // Simplified JavaScript code to reinitialize Bloodhound
let js_code = format!( let js_code = format!(
r#" r##"
try {{ try {{
console.log("[DEBUG] Input focused:", "{}");
// Get the input element // Get the input element
const inputElement = document.getElementById("{}"); const inputElement = document.getElementById("{}");
if (!inputElement) {{ if (!inputElement) {{
console.error("[DEBUG] Input element not found:", "{}"); console.error("[RUST] Input element not found:", "{}");
return; return;
}} }}
// Check if Bloodhound is initialized // Force Bloodhound to reinitialize
if (!window.bloodhoundInstances || !window.bloodhoundInstances["{}"]) {{ if (typeof window.initTypeahead === "function") {{
console.warn("[DEBUG] Bloodhound not initialized for {}, attempting to reinitialize", "{}"); window.initTypeahead("#{}", "{}");
console.log("[RUST] Reinitialized Bloodhound for {}", "{}");
// Try to reinitialize Bloodhound
if (typeof window.initTypeahead === "function") {{
window.initTypeahead("{}", "{}");
console.log("[DEBUG] Reinitialized Bloodhound for {}", "{}");
}} else {{
console.error("[DEBUG] initTypeahead function not available ");
}}
}} else {{
console.log("[DEBUG] Bloodhound already initialized for {}", "{}");
// Force a query if there's a value // Force a query if there's a value
if (inputElement.value) {{ if (inputElement.value) {{
// Directly manipulate the DOM to trigger Bloodhound
const currentValue = inputElement.value;
// Clear and reset the value to force Bloodhound to update
inputElement.value = "";
setTimeout(function() {{ setTimeout(function() {{
inputElement.value = currentValue; // Trigger an input event
inputElement.dispatchEvent(new Event("input", {{ bubbles: true }})); const event = new Event("input", {{ bubbles: true }});
console.log("[DEBUG] Forced input event for {} with value: {}", "{}", currentValue); inputElement.dispatchEvent(event);
}}, 10); console.log("[RUST] Forced input event for {} with value: {}", "{}", inputElement.value);
}}, 50);
}} }}
}} }}
}} catch (e) {{ }} catch (e) {{
console.error("[DEBUG] Error in focus handler:", e); console.error("[RUST] Error in focus handler:", e);
}} }}
"#, "##,
input_id, input_id, input_id,
input_id, input_id,
input_id, input_id, input_id,
input_id, input_id, input_id, input_id, input_id, input_id, input_id, input_id,
input_id, input_id,
input_id, input_id, input_id input_id, input_id, input_id
); );