fix: component pass thru events
This commit is contained in:
1 parent
b49928a4ac
commit
c439b0ac7e
7 files changed
+37
-31
No files matched your search
@@ -41,22 +41,22 @@ fn app(cx: Scope) -> Element {
|
|||||||
div { class: "col-md-6",
|
div { class: "col-md-6",
|
||||||
div { class: "row",
|
div { class: "row",
|
||||||
ActionButton { name: "Create 1,000 rows", id: "run",
|
ActionButton { name: "Create 1,000 rows", id: "run",
|
||||||
onclick: move || items.set(Label::new_list(1_000)),
|
onclick: move |_| items.set(Label::new_list(1_000)),
|
||||||
}
|
}
|
||||||
ActionButton { name: "Create 10,000 rows", id: "runlots",
|
ActionButton { name: "Create 10,000 rows", id: "runlots",
|
||||||
onclick: move || items.set(Label::new_list(10_000)),
|
onclick: move |_| items.set(Label::new_list(10_000)),
|
||||||
}
|
}
|
||||||
ActionButton { name: "Append 1,000 rows", id: "add",
|
ActionButton { name: "Append 1,000 rows", id: "add",
|
||||||
onclick: move || items.write().extend(Label::new_list(1_000)),
|
onclick: move |_| items.write().extend(Label::new_list(1_000)),
|
||||||
}
|
}
|
||||||
ActionButton { name: "Update every 10th row", id: "update",
|
ActionButton { name: "Update every 10th row", id: "update",
|
||||||
onclick: move || items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
|
onclick: move |_| items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
|
||||||
}
|
}
|
||||||
ActionButton { name: "Clear", id: "clear",
|
ActionButton { name: "Clear", id: "clear",
|
||||||
onclick: move || items.write().clear(),
|
onclick: move |_| items.write().clear(),
|
||||||
}
|
}
|
||||||
ActionButton { name: "Swap rows", id: "swaprows",
|
ActionButton { name: "Swap rows", id: "swaprows",
|
||||||
onclick: move || items.write().swap(0, 998),
|
onclick: move |_| items.write().swap(0, 998),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
struct ActionButtonProps<'a> {
|
struct ActionButtonProps<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
id: &'a str,
|
id: &'a str,
|
||||||
onclick: &'a dyn Fn(),
|
onclick: EventHandler<'a, ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
|
fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
|
||||||
@@ -102,7 +102,7 @@ fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
|
|||||||
class:"btn btn-primary btn-block",
|
class:"btn btn-primary btn-block",
|
||||||
r#type: "button",
|
r#type: "button",
|
||||||
id: "{cx.props.id}",
|
id: "{cx.props.id}",
|
||||||
onclick: move |_| (cx.props.onclick)(),
|
onclick: move |_| cx.props.onclick.call(()),
|
||||||
|
|
||||||
"{cx.props.name}"
|
"{cx.props.name}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
//! the RefCell will panic and crash. You can use `try_get_mut` or `.modify` to avoid this problem, or just not hold two
|
//! the RefCell will panic and crash. You can use `try_get_mut` or `.modify` to avoid this problem, or just not hold two
|
||||||
//! RefMuts at the same time.
|
//! RefMuts at the same time.
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use dioxus::desktop::wry::application::dpi::LogicalSize;
|
use dioxus::desktop::wry::application::dpi::LogicalSize;
|
||||||
use dioxus::events::*;
|
use dioxus::events::*;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
@@ -117,7 +115,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct CalculatorKeyProps<'a> {
|
struct CalculatorKeyProps<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
onclick: &'a dyn Fn(MouseEvent),
|
onclick: EventHandler<'a, MouseEvent>,
|
||||||
children: Element<'a>,
|
children: Element<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +123,7 @@ fn CalculatorKey<'a>(cx: Scope<'a, CalculatorKeyProps<'a>>) -> Element {
|
|||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
button {
|
button {
|
||||||
class: "calculator-key {cx.props.name}",
|
class: "calculator-key {cx.props.name}",
|
||||||
onclick: move |e| (cx.props.onclick)(e),
|
onclick: move |e| cx.props.onclick.call(e),
|
||||||
&cx.props.children
|
&cx.props.children
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ impl ToTokens for ContentField {
|
|||||||
__cx.raw_text(format_args_f!(#s)).0
|
__cx.raw_text(format_args_f!(#s)).0
|
||||||
}),
|
}),
|
||||||
ContentField::OnHandlerRaw(e) => tokens.append_all(quote! {
|
ContentField::OnHandlerRaw(e) => tokens.append_all(quote! {
|
||||||
__cx.bump().alloc(#e)
|
__cx.event_handler(#e)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-11
@@ -316,29 +316,33 @@ pub struct Listener<'bump> {
|
|||||||
pub event: &'static str,
|
pub event: &'static str,
|
||||||
|
|
||||||
/// The actual callback that the user specified
|
/// The actual callback that the user specified
|
||||||
pub(crate) callback: EventHandler<'bump>,
|
pub(crate) callback: InternalHandler<'bump>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The callback based into element event listeners.
|
pub type InternalHandler<'bump> = &'bump RefCell<Option<InternalListenerCallback<'bump>>>;
|
||||||
pub struct EventHandler<'bump> {
|
type InternalListenerCallback<'bump> = BumpBox<'bump, dyn FnMut(AnyEvent) + 'bump>;
|
||||||
pub callback: &'bump RefCell<Option<ListenerCallback<'bump>>>,
|
|
||||||
|
type ExternalListenerCallback<'bump, T> = BumpBox<'bump, dyn FnMut(T) + 'bump>;
|
||||||
|
|
||||||
|
/// The callback based through the `rsx!` macro.
|
||||||
|
pub struct EventHandler<'bump, T = ()> {
|
||||||
|
pub callback: &'bump RefCell<Option<ExternalListenerCallback<'bump, T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler<'_> {
|
impl<T> EventHandler<'_, T> {
|
||||||
pub fn call(&self, event: AnyEvent) {
|
pub fn call(&self, event: T) {
|
||||||
if let Some(callback) = self.callback.borrow_mut().as_mut() {
|
if let Some(callback) = self.callback.borrow_mut().as_mut() {
|
||||||
callback(event);
|
callback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(&self) {
|
pub fn release(&self) {
|
||||||
self.callback.replace(None);
|
self.callback.replace(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListenerCallback<'bump> = BumpBox<'bump, dyn FnMut(AnyEvent) + 'bump>;
|
impl<T> Copy for EventHandler<'_, T> {}
|
||||||
|
impl<T> Clone for EventHandler<'_, T> {
|
||||||
impl Copy for EventHandler<'_> {}
|
|
||||||
impl Clone for EventHandler<'_> {
|
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
callback: self.callback,
|
callback: self.callback,
|
||||||
@@ -551,7 +555,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
VNode::Component(vcomp)
|
VNode::Component(vcomp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listener(self, event: &'static str, callback: EventHandler<'a>) -> Listener<'a> {
|
pub fn listener(self, event: &'static str, callback: InternalHandler<'a>) -> Listener<'a> {
|
||||||
Listener {
|
Listener {
|
||||||
event,
|
event,
|
||||||
mounted_node: Cell::new(None),
|
mounted_node: Cell::new(None),
|
||||||
@@ -643,6 +647,13 @@ impl<'a> NodeFactory<'a> {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn event_handler<T>(self, f: impl FnMut(T) + 'a) -> EventHandler<'a, T> {
|
||||||
|
let handler: &mut dyn FnMut(T) = self.bump.alloc(f);
|
||||||
|
let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
|
||||||
|
let callback = self.bump.alloc(RefCell::new(Some(caller)));
|
||||||
|
EventHandler { callback }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for NodeFactory<'_> {
|
impl Debug for NodeFactory<'_> {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ impl ScopeArena {
|
|||||||
items
|
items
|
||||||
.listeners
|
.listeners
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.for_each(|listener| drop(listener.callback.callback.borrow_mut().take()));
|
.for_each(|listener| drop(listener.callback.borrow_mut().take()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ impl ScopeArena {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cb = listener.callback.callback.borrow_mut();
|
let mut cb = listener.callback.borrow_mut();
|
||||||
if let Some(cb) = cb.as_mut() {
|
if let Some(cb) = cb.as_mut() {
|
||||||
// todo: arcs are pretty heavy to clone
|
// todo: arcs are pretty heavy to clone
|
||||||
// we really want to convert arc to rc
|
// we really want to convert arc to rc
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, Ref, RefCell, RefMut},
|
cell::{Ref, RefCell, RefMut},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,7 @@ pub mod on {
|
|||||||
// ie copy
|
// ie copy
|
||||||
let shortname: &'static str = &event_name[2..];
|
let shortname: &'static str = &event_name[2..];
|
||||||
|
|
||||||
let handler = EventHandler {
|
let handler = bump.alloc(std::cell::RefCell::new(Some(callback)));
|
||||||
callback: bump.alloc(std::cell::RefCell::new(Some(callback))),
|
|
||||||
};
|
|
||||||
|
|
||||||
factory.listener(shortname, handler)
|
factory.listener(shortname, handler)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|||||||
Reference in new issue
Block a user