Clone in a terminal:
Commit 8def408
Johan Mattsson - 2026-07-10T12:16:23+00:00
8def408f49391c13eaf0520f83d58cabb61ff462johan.mattsson.m@gmail.com

New example component

Changed files (4)

Diff

diff --git a/examples/main-component/src/lib.rs b/examples/main-component/src/lib.rsindex b82c302..868c178 100644--- a/examples/main-component/src/lib.rs+++ b/examples/main-component/src/lib.rs@@ -1,6 +1,4 @@-use crate::main_component::init_test_loop; use kaja_web::prelude::*;-mod main_component;  #[wasm_bindgen(start)] pub fn init() {@@ -8,5 +6,4 @@ pub fn init() {     console_error_panic_hook::set_once();      init_callbacks();-    init_test_loop(); }diff --git a/examples/main-component/src/main_component.rs b/examples/main-component/src/main_component.rsindex c1a1a6b..f97a654 100644--- a/examples/main-component/src/main_component.rs+++ b/examples/main-component/src/main_component.rs@@ -1,30 +1,28 @@ use crate::log; use async_channel::{Receiver, Sender};-use kaja_web::update; use std::collections::HashMap; use std::sync::{Arc, LazyLock, Mutex, OnceLock, RwLock}; use wasm_bindgen::JsCast; use wasm_bindgen::prelude::*; -#[derive(Default)]+#[component("main-component")] struct Main {     test: bool, } -#[derive(Default)]+#[component("other-component")] struct Other {     the_number: i32, } -trait Component {-    fn update(id: &str)-    where-        Self: Sized;-}- impl Component for Main {+    fn connected(id: &str) {+        #[cfg(feature = "threads")]+        start_background(id);+    }+     fn update(id: &str) {-        log!("Main update:", id);+        log!("Main ui_thread_update:", id);         let handle = Self::get_component_arc(id);         let mut component = handle.lock().unwrap(); @@ -41,91 +39,32 @@ impl Main {     } } -impl Main {-    fn get_component_arc(_id: &str) -> Arc<Mutex<Main>> {-        Arc::new(Mutex::new(Main::default()))-    }-}- impl Component for Other {-    fn update(id: &str) {+    fn ui_thread_update(id: &str) {         log!("Other update:", id);     } } -static UPDATE_SENDER: OnceLock<Sender<String>> = OnceLock::new();--pub fn schedule_update(id: &str) {-    if let Some(sender) = UPDATE_SENDER.get() {-        match sender.try_send(id.to_string()) {-            Ok(_) => {-                log!("scheduled update for:", id);-            }-            Err(e) => {-                log!("could not schedule update for", id);-            }-        }-    }-}--async fn ui_update_loop(receiver: Receiver<String>) {-    while let Ok(id) = receiver.recv().await {-        update(&id);-    }-}--static MAIN_COMPONENT: LazyLock<RwLock<HashMap<String, Arc<Mutex<Main>>>>> =-    LazyLock::new(|| RwLock::new(HashMap::new()));--fn update_component_main(id: &str) -> bool {-    {-        let lock = MAIN_COMPONENT-            .read()-            .expect("Failed to lock MAIN_COMPONENT");--        if !lock.contains_key(id) {-            return false;-        }-    }--    Main::update(id);-    true-}- #[cfg(not(feature = "threads"))]-fn start_background(sender: Sender<String>) {+fn start_background(id: &str) {+    let component_id = id.to_string();+     wasm_bindgen_futures::spawn_local(async move {         loop {-            schedule_update("main-component-1"); // await?-            schedule_update("other-component-1"); // await?-+            post_ui_thread_update(component_id.as_str()); // await?             gloo_timers::future::TimeoutFuture::new(1000).await;         }     }); }  #[cfg(feature = "threads")]-fn start_background(sender: Sender<String>) {+fn start_background(id: &str) {+    let component_id = id.to_string();+     std::thread::spawn(move || {         loop {-            schedule_update("main-component-1");-            schedule_update("other-component-1");-+            post_ui_thread_update(component_id.as_str());             std::thread::sleep(std::time::Duration::from_secs(1));         }     }); }--pub fn init_test_loop() {-    let (sender, receiver) = async_channel::unbounded::<String>();--    UPDATE_SENDER-        .set(sender.clone())-        .expect("UPDATE_SENDER already initialized");--    // This runs on the browser UI thread-    wasm_bindgen_futures::spawn_local(ui_update_loop(receiver));--    #[cfg(feature = "threads")]-    start_background(sender);-}diff --git a/src/lib.rs b/src/lib.rsindex 7f931af..fc0f139 100644--- a/src/lib.rs+++ b/src/lib.rs@@ -17,9 +17,6 @@ inventory::collect!(InitFn); pub struct InitComponentFn(pub fn()); inventory::collect!(InitComponentFn); -pub struct UpdateComponentFn(pub fn(id: &str) -> bool);-inventory::collect!(UpdateComponentFn);- /// Global counter shared by all components created by the #[component] macro. /// The proc-macro-generated code will increment this to obtain a unique wasm id. pub static NEXT_COMPONENT_COUNTER: std::sync::atomic::AtomicU32 =@@ -80,16 +77,6 @@ pub fn init_callbacks() {     } } -pub fn update(id: &str) {-    for init in inventory::iter::<UpdateComponentFn> {-        let result = (init.0)(id);--        if result {-            return;-        }-    }-}- /// Queries the document for a single element matching the given selector. /// Returns `None` if no element is found. Returns first matching element if multiple are found. pub fn get_element(selector: &str) -> Option<HtmlElement> {@@ -337,30 +324,12 @@ pub fn get_callback(name: &str) -> Option<js_sys::Function> {  /// HTML Component. See kaja-web-component. pub trait Component {-    fn connected(&mut self, _parent: HtmlElement) {}-    fn disconnected(&mut self, _parent: HtmlElement) {}-    fn observed_attributes() -> &'static [&'static str] {-        &[]-    }--    fn attribute_changed(-        &mut self,-        _parent: HtmlElement,-        name: &str,-        _old_value: &str,-        _new_value: &str,-    ) {+    fn connected(id: &str) {}+    fn disconnected(id: &str) {}+    fn attribute_changed(id: &str, name: &str, _old_value: &str, _new_value: &str) {         log!("Attribute changed but no update handler for ", name);     }--    /// Render the component into the given element.-    fn render(&self, _element: &HtmlElement) {}-}--pub fn get_component_element(id: &str) -> Option<HtmlElement> {-    let selector = format!("[componentid='{}']", id);-    let element = get_element(selector.as_str());-    element+    fn update(id: &str) {} }  pub fn get_element_by_id(id: &str) -> Option<HtmlElement> {@@ -369,44 +338,6 @@ pub fn get_element_by_id(id: &str) -> Option<HtmlElement> {     element } -pub trait ComponentStorage: Sized {-    fn storage() -> &'static RwLock<Option<HashMap<String, std::sync::Arc<std::sync::Mutex<Self>>>>>;-}--/// Returns a cloned Arc pointing to the stored component. The component itself is-/// protected by an `RwLock` so callers can lock it for mutable or shared access when needed.-pub fn get_component<T: ComponentStorage + 'static>(-    id: &str,-) -> Option<std::sync::Arc<std::sync::Mutex<T>>> {-    let map_lock = T::storage().read();--    if map_lock.is_err() {-        error!("Failed to take storage lock");-        return None;-    }--    let store_opt = map_lock.unwrap();--    if store_opt.is_none() {-        error!("Store not initialized");-        return None;-    }--    let map = store_opt.as_ref().unwrap();-    map.get(id).cloned()-}--pub fn get_component_id(element: &HtmlElement) -> String {-    let id = element.get_attribute("componentid");--    if id.is_none() {-        error!("No component id is set for element.");-        return "".to_string();-    }--    id.unwrap()-}- // Example: let count = get_value!(&id, Counter.field); #[macro_export] macro_rules! get_value {@@ -427,24 +358,6 @@ macro_rules! set_value {     }}; } -pub fn rerender<T>(id: &str)-where-    T: ComponentStorage + Component + 'static,-{-    let component = get_component::<T>(id);-    let binding = component.unwrap();-    let component_binding = binding.lock().unwrap();-    let html_element = get_component_element(id);--    if html_element.is_none() {-        error!("No html_element in rerender.");-        return;-    }--    let element = html_element.unwrap();-    component_binding.render(&element);-}- pub fn remove_css_class(element: &HtmlElement, css_class: &str) {     use js_sys::Array;     use wasm_bindgen::JsValue;diff --git a/src/prelude.rs b/src/prelude.rsindex 121caab..9ee4ddd 100644--- a/src/prelude.rs+++ b/src/prelude.rs@@ -1,8 +1,7 @@ pub use crate::{-    CallbackRegistration, Component, ComponentStorage, Error, InitComponentFn, InitFn, Result,-    get_callback, get_component, get_component_element, get_component_id, get_cookie_value,-    get_element, get_element_by_id, get_elements, get_value, init_callbacks, inner_html,-    inner_text, rerender, set_value, try_get_value, try_inner_html, try_inner_text,+    CallbackRegistration, Component, Error, InitComponentFn, InitFn, Result, get_callback,+    get_cookie_value, get_element, get_element_by_id, get_elements, get_value, init_callbacks,+    inner_html, inner_text, set_value, try_get_value, try_inner_html, try_inner_text, };  pub use gloo::console::error;

Contact

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