feat(items_list): add row after suggestion selection other than on input

This commit is contained in:
ryan 2025-05-26 14:18:27 +03:00
parent 5577f855ca
commit d565563edb
2 changed files with 51 additions and 36 deletions

View file

@ -865,12 +865,21 @@ pub fn ItemsList(
<TypeaheadInput <TypeaheadInput
value=item.name.clone() value=item.name.clone()
fetch_suggestions=Callback::new({ fetch_suggestions=Callback::new({
let key = format!("name-{}", index); // Use the item's unique ID in the key to ensure uniqueness
let key = format!("name-{}-{}", index, item.id);
let wikidata_suggestions_clone = wikidata_suggestions.clone(); let wikidata_suggestions_clone = wikidata_suggestions.clone();
move |query: String| -> Vec<WikidataSuggestion> { move |query: String| -> Vec<WikidataSuggestion> {
// Only fetch suggestions if the query is not empty
if !query.is_empty() {
// Fetch suggestions in a separate function to avoid capturing too much // Fetch suggestions in a separate function to avoid capturing too much
fetch_wikidata_suggestions(key.clone(), query.clone()); fetch_wikidata_suggestions(key.clone(), query.clone());
} else {
// Clear suggestions for this key if query is empty
set_wikidata_suggestions.update(|suggestions| {
suggestions.remove(&key);
});
}
// Return current suggestions from the signal // Return current suggestions from the signal
let suggestions = wikidata_suggestions_clone.get(); let suggestions = wikidata_suggestions_clone.get();
@ -885,11 +894,12 @@ pub fn ItemsList(
let property_labels_clone = property_labels.clone(); let property_labels_clone = property_labels.clone();
let current_url_clone = Rc::clone(&current_url_clone); let current_url_clone = Rc::clone(&current_url_clone);
let selected_properties_clone = selected_properties.clone(); let selected_properties_clone = selected_properties.clone();
let items_len = items.len(); // Get the current items length let items_len = items.len();
move |suggestion: WikidataSuggestion| { move |suggestion: WikidataSuggestion| {
let wikidata_id = suggestion.id.clone(); let wikidata_id = suggestion.id.clone();
// Update the current item with the selected suggestion
set_items_clone.update(|items| { set_items_clone.update(|items| {
if let Some(item) = items.get_mut(index) { if let Some(item) = items.get_mut(index) {
item.name = suggestion.display.label.value.clone(); item.name = suggestion.display.label.value.clone();
@ -915,12 +925,9 @@ pub fn ItemsList(
).await; ).await;
}); });
// Add a new row if this is the last row // Add a new row if this is the last row - in a separate update call
if index == items_len - 1 { if index == items_len - 1 {
let current_url_for_new_item = Rc::clone(&current_url_clone); // First, create a completely new item
let selected_properties_for_new_item = selected_properties_clone.clone();
set_items_clone.update(|items| {
let new_item = Item { let new_item = Item {
id: Uuid::new_v4().to_string(), id: Uuid::new_v4().to_string(),
name: String::new(), name: String::new(),
@ -928,10 +935,18 @@ pub fn ItemsList(
wikidata_id: None, wikidata_id: None,
custom_properties: HashMap::new(), custom_properties: HashMap::new(),
}; };
items.push(new_item.clone());
// Clone for database save
let new_item_clone = new_item.clone();
let current_url_for_new_item = Rc::clone(&current_url_clone);
let selected_properties_for_new_item = selected_properties_clone.clone();
// Add the new item in a separate update to force re-rendering
set_items_clone.update(|items| {
items.push(new_item);
});
// Save the new item to the database in a separate task // Save the new item to the database in a separate task
let new_item_clone = new_item.clone();
let current_url_for_task = Rc::clone(&current_url_for_new_item); let current_url_for_task = Rc::clone(&current_url_for_new_item);
let selected_properties_for_task = selected_properties_for_new_item; let selected_properties_for_task = selected_properties_for_new_item;
@ -942,7 +957,6 @@ pub fn ItemsList(
current_url_for_task.to_string() current_url_for_task.to_string()
).await; ).await;
}); });
});
} }
} }
}) })
@ -954,7 +968,7 @@ pub fn ItemsList(
} }
}) })
node_ref=node_ref.clone() node_ref=node_ref.clone()
id=format!("name-input-{}", index) id=format!("name-input-{}-{}", index, item.id)
/> />
</div> </div>
}.into_view(), }.into_view(),

View file

@ -100,6 +100,7 @@ pub fn TypeaheadInput(
#[prop(optional)] is_last_row: bool, #[prop(optional)] is_last_row: bool,
#[prop(optional)] on_input: Option<Callback<String>>, #[prop(optional)] on_input: Option<Callback<String>>,
#[prop(optional)] id: Option<String>, #[prop(optional)] id: Option<String>,
#[prop(optional)] key: Option<String>,
) -> impl IntoView { ) -> impl IntoView {
let (is_initialized, set_initialized) = create_signal(false); let (is_initialized, set_initialized) = create_signal(false);
@ -523,12 +524,12 @@ pub fn TypeaheadInput(
let value = event_target_value(&ev); let value = event_target_value(&ev);
log!("[INPUT] Value changed: {} ({})", value, component_id_for_input); log!("[INPUT] Value changed: {} ({})", value, component_id_for_input);
// If this is the last row and we have an on_input callback, call it // // If this is the last row and we have an on_input callback, call it
if is_last_row && !value.is_empty() { // if is_last_row && !value.is_empty() {
if let Some(callback) = &on_input { // if let Some(callback) = &on_input {
callback.call(value.clone()); // callback.call(value.clone());
} // }
} // }
} }
/> />
} }