Clone in a terminal:
Commit 0cd2174
Johan Mattsson - 2026-06-30T10:30:41+00:00
0cd2174fed7d13a01eeb3cb5336936321d14910cjohan.mattsson.m@gmail.com

Update function for components referenced by id

Changed files (4)

Diff

diff --git a/examples/counter-component/src/counter.rs b/examples/counter-component/src/counter.rsindex 54407e9..a6a82a5 100644--- a/examples/counter-component/src/counter.rs+++ b/examples/counter-component/src/counter.rs@@ -5,7 +5,7 @@ pub struct Counter {     value: i32, } -impl Component for Counter {+impl Counter {     fn connected(&mut self, element: HtmlElement) {         self.render(&element);     }@@ -38,19 +38,11 @@ impl Counter {             return;         } -        let component_id = element.get_attribute("componentid");--        if component_id.is_none() {-            log!("No component_id.");-            return;-        }--        let id = component_id.unwrap();-+        let component_id = self.get_component_id();         let content = html! {{             <p>                 Count: $(count.unwrap())-                <button onclick="increment('$id');">Increment</button>+                <button onclick="increment('$component_id');">Increment</button>             </p>         }}; @@ -60,39 +52,34 @@ impl Counter {  #[callback(increment)] pub fn increment(id: String) {-    let element = get_component_element(id.as_str());--    if element.is_none() {-        error!("Element not found for id", id);-        return;-    }+    log!("increment");+    // id is a String from the callback; update_component accepts AsRef<str>.+    update_component(id, |component: &mut Counter, element: &HtmlElement| {+        log!("update_component", component.get_component_id());+        increment_component(component, element);+    });+} -    let html_element = element.unwrap();-    let count_attribute = html_element.get_attribute("count");+fn increment_component(component: &mut Counter, element: &HtmlElement) {+    let count_attribute = element.get_attribute("count");      if count_attribute.is_none() {-        error!("Attribute count not found for id", id);+        error!("Attribute 'count' not found for element");         return;     } -    let count = count_attribute.unwrap().parse::<i32>();--    if !count.is_ok() {+    let count_res = count_attribute.unwrap().parse::<i32>();+    if count_res.is_err() {         error!("Count is not an integer.");         return;     } -    let mut current_count = count.unwrap();-    current_count += 1;+    let new_count = count_res.unwrap() + 1; -    if let Some(counter_arc) = get_component::<Counter>(id.as_str()) {-        let mut counter = counter_arc.lock().unwrap();-        counter.value = current_count;-        counter.render(&html_element);-    } else {-        error!("Component not found for id", id);-        return;-    }+    component.value = new_count;+    element.set_attribute("count", new_count.to_string().as_str());++    log!("new count", new_count); -    let _ = html_element.set_attribute("count", current_count.to_string().as_str());+    component.render(element); }diff --git a/examples/counter-component/src/main_component.rs b/examples/counter-component/src/main_component.rsindex 0218ae7..993a64d 100644--- a/examples/counter-component/src/main_component.rs+++ b/examples/counter-component/src/main_component.rs@@ -5,7 +5,7 @@ pub struct Main {     message: Option<String>, } -impl Component for Main {+impl Main {     fn connected(&mut self, element: HtmlElement) {         self.render(element);     }diff --git a/src/lib.rs b/src/lib.rsindex 7ee63d7..f2aae00 100644--- a/src/lib.rs+++ b/src/lib.rs@@ -4,7 +4,7 @@ #![doc = include_str!("../README.md")]  use gloo_console::{error, log};-use wasm_bindgen::{JsCast, JsValue};+use wasm_bindgen::JsCast; use web_sys::{Element, HtmlDocument, HtmlElement, HtmlInputElement, NodeList};  pub mod prelude;@@ -339,6 +339,8 @@ pub trait Component {     ) {         log!("Attribute changed but no update handler for ", name);     }++    fn get_component_id(&self) -> String; }  pub fn get_component_element(id: &str) -> Option<HtmlElement> {@@ -373,3 +375,38 @@ pub fn get_component<T: ComponentStorage + 'static>(     let map = store_opt.as_ref().unwrap();     map.get(id).cloned() }++pub fn update_component<F, T, S>(id: S, callback: F)+where+    S: AsRef<str>,+    F: Fn(&mut T, &HtmlElement),+    T: ComponentStorage + 'static,+{+    let id_ref = id.as_ref();+    let element_opt = get_component_element(id_ref);++    if element_opt.is_none() {+        error!("Element not found for id", id_ref);+        return;+    }++    let element = element_opt.unwrap();++    let component_opt = get_component::<T>(id_ref);++    if component_opt.is_none() {+        error!("Component not found for id", id_ref);+        return;+    }++    let component_arc = component_opt.unwrap();+    match component_arc.try_lock() {+        Ok(mut component) => {+            callback(&mut component, &element);+        }+        Err(_) => {+            error!("Can't lock component for id", id_ref);+            return;+        }+    }+}diff --git a/src/prelude.rs b/src/prelude.rsindex 0e348a7..b847bc7 100644--- a/src/prelude.rs+++ b/src/prelude.rs@@ -2,7 +2,7 @@ pub use crate::{     CallbackRegistration, Component, ComponentStorage, Error, InitComponentFn, InitFn, Result,     get_callback, get_component, get_component_element, get_cookie_value, get_element,     get_elements, get_value, init_callbacks, inner_html, inner_text, try_get_value, try_inner_html,-    try_inner_text,+    try_inner_text, update_component, };  pub use gloo::console::error;

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112