Pauan / rust-dominator

Zero-cost ultra-high-performance declarative DOM library using FRP signals for Rust!
MIT License
960 stars 62 forks source link

Add `show_picker()` functionality to `focused_signal()` Upon wasm-bindgen/issues/3036 being implemented. #73

Open Billy-Sheppard opened 1 year ago

Billy-Sheppard commented 1 year ago

Focused signal works great for text inputs but for picker style inputs it doesn't work.

Unsure exactly how to implement it though, also heavily dependant on how/if/when the wasm-bindgen guys get the following issue working.

https://github.com/rustwasm/wasm-bindgen/issues/3036

pub(crate) fn show_picker(elem: &HtmlElement) {
    elem.show_picker().unwrap_throw();
}
fn set_focused_signal<B>(&mut self, value: B)
        where B: Signal<Item = bool> + 'static {

        let element = self.element.as_ref().clone();

        // This needs to use `after_insert` because calling `.focus()` on an element before it is in the DOM has no effect
        self.callbacks.after_insert(move |callbacks| {
            // TODO verify that this is correct under all circumstances
            callbacks.after_remove(for_each(value, move |value| {
                // TODO avoid updating if the focused state hasn't changed ?
                if value {
                    bindings::focus(&element);
                }
                else if value { // && [ "date", "datetime-local", "month", "time", "week", "color", "file"].contains(input_type) ??
                    bindings::show_picker(&element); // COULD ADD HERE?
                } else {
                    bindings::blur(&element);
                    // NOT SURE HOW TO HANDLE BLUR-ING
                }
            }));
        });
    }
Pauan commented 1 year ago

I think we have to wait for it to be stabilized, I don't want to rely on unstable APIs.

Also, it sounds like you can only call it inside of an event listener, like click. You can't just call it whenever you want.

So in that case there's nothing that dominator can do, you can instead use it like this:

html!("input" => HtmlInputElement, {
    .with_node!(element => {
        .event(move |_: events::Click| {
            element.show_picker();
        })
    })
})

This works without any changes needed to dominator.

Billy-Sheppard commented 1 year ago

Interesting, thanks Pauan.

Am I correct in thinking that the with_node! macro behind the scenes calls __internal_element()?

Pauan commented 1 year ago

Yes, but that's a completely internal implementation detail that you shouldn't rely upon.

What you can rely upon is that it gives you the raw web_sys DOM node which is being wrapped by DomBuilder.

Since it's a web_sys DOM node, you can of course call all of the web_sys methods on it.

Billy-Sheppard commented 1 year ago

The reason I am hesitant to use with_node! is I try to avoid using macros if possible (due to a few reasons but primarily that it can cause issues with rust-fmt).

Is there a reason its not a properly/"publicly" implemented method?