mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
Update NodeRef
to be generic over typed HTML elements
This commit is contained in:
parent
351389c2bf
commit
ce84632c39
3 changed files with 24 additions and 24 deletions
|
@ -262,7 +262,7 @@ pub fn Todo(cx: Scope, todo: Todo) -> impl IntoView {
|
|||
let set_todos = use_context::<WriteSignal<Todos>>(cx).unwrap();
|
||||
|
||||
// this will be filled by _ref=input below
|
||||
let input = NodeRef::new(cx);
|
||||
let todo_input = NodeRef::new(cx);
|
||||
|
||||
let save = move |value: &str| {
|
||||
let value = value.trim();
|
||||
|
@ -282,7 +282,7 @@ pub fn Todo(cx: Scope, todo: Todo) -> impl IntoView {
|
|||
>
|
||||
<div class="view">
|
||||
<input
|
||||
_ref=input
|
||||
_ref=todo_input
|
||||
class="toggle"
|
||||
type="checkbox"
|
||||
prop:checked={move || (todo.completed)()}
|
||||
|
@ -293,12 +293,9 @@ pub fn Todo(cx: Scope, todo: Todo) -> impl IntoView {
|
|||
/>
|
||||
<label on:dblclick=move |_| {
|
||||
set_editing(true);
|
||||
|
||||
if let Some(input) = input.get()
|
||||
.as_ref()
|
||||
.and_then(|n| n.dyn_ref::<HtmlInputElement>())
|
||||
{
|
||||
input.focus();
|
||||
|
||||
if let Some(input) = todo_input.get() {
|
||||
_ = input.focus();
|
||||
}
|
||||
}>
|
||||
{move || todo.title.get()}
|
||||
|
|
|
@ -14,12 +14,12 @@ cfg_if! {
|
|||
|
||||
/// Trait alias for the trait bounts on [`IntoElement`].
|
||||
pub trait IntoElementBounds:
|
||||
fmt::Debug + AsRef<web_sys::HtmlElement>
|
||||
fmt::Debug + AsRef<web_sys::HtmlElement> + Clone
|
||||
{
|
||||
}
|
||||
|
||||
impl<El> IntoElementBounds for El where
|
||||
El: fmt::Debug + AsRef<web_sys::HtmlElement>
|
||||
El: fmt::Debug + AsRef<web_sys::HtmlElement> + Clone
|
||||
{
|
||||
}
|
||||
} else {
|
||||
|
@ -202,6 +202,7 @@ impl IntoElement for Custom {
|
|||
cfg_if! {
|
||||
if #[cfg(all(target_arch = "wasm32", feature = "web"))] {
|
||||
/// Represents an HTML element.
|
||||
#[derive(Clone)]
|
||||
pub struct HtmlElement<El: IntoElement> {
|
||||
pub(crate) cx: Scope,
|
||||
pub(crate) element: El,
|
||||
|
@ -209,7 +210,7 @@ cfg_if! {
|
|||
// Server needs to build a virtualized DOM tree
|
||||
} else {
|
||||
/// Represents an HTML element.
|
||||
#[derive(educe::Educe)]
|
||||
#[derive(educe::Educe, Clone)]
|
||||
#[educe(Debug)]
|
||||
pub struct HtmlElement<El: IntoElement> {
|
||||
pub(crate) cx: Scope,
|
||||
|
@ -225,12 +226,12 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<El: IntoElement> std::ops::Deref for HtmlElement<El> {
|
||||
type Target = web_sys::HtmlElement;
|
||||
impl<El> std::ops::Deref for HtmlElement<El> where El: IntoElement + std::ops::Deref {
|
||||
type Target = <El as std::ops::Deref>::Target;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
return self.element.as_ref();
|
||||
return self.element.deref();
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
unimplemented!("{HTML_ELEMENT_DEREF_UNIMPLEMENTED_MSG}");
|
||||
|
@ -341,7 +342,7 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
}
|
||||
|
||||
/// Binds the element reference to [`NodeRef`].
|
||||
pub fn node_ref(self, node_ref: &NodeRef) -> Self {
|
||||
pub fn node_ref(self, node_ref: &NodeRef<Self>) -> Self where Self: Clone {
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
node_ref.load(&self);
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ use leptos_reactive::{create_rw_signal, RwSignal, Scope};
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct NodeRef(RwSignal<Option<web_sys::Element>>);
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct NodeRef<T: Clone + 'static>(RwSignal<Option<T>>);
|
||||
|
||||
impl NodeRef {
|
||||
impl<T: Clone + 'static> NodeRef<T> {
|
||||
/// Creates an empty reference.
|
||||
pub fn new(cx: Scope) -> Self {
|
||||
Self(create_rw_signal(cx, None))
|
||||
|
@ -43,7 +43,7 @@ impl NodeRef {
|
|||
/// Initially, the value will be `None`, but once it is loaded the effect
|
||||
/// will rerun and its value will be `Some(Element)`.
|
||||
#[track_caller]
|
||||
pub fn get(&self) -> Option<web_sys::Element> {
|
||||
pub fn get(&self) -> Option<T> {
|
||||
self.0.get()
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ impl NodeRef {
|
|||
/// so that effects that use the node reference will rerun once it is loaded,
|
||||
/// i.e., effects can be forward-declared.
|
||||
#[track_caller]
|
||||
pub fn load(&self, node: &web_sys::Element) {
|
||||
pub fn load(&self, node: &T) {
|
||||
self.0.update(|current| {
|
||||
if current.is_some() {
|
||||
crate::debug_warn!(
|
||||
|
@ -66,23 +66,25 @@ impl NodeRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + 'static> Copy for NodeRef<T> { }
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(feature = "stable"))] {
|
||||
impl FnOnce<()> for NodeRef {
|
||||
type Output = Option<web_sys::Element>;
|
||||
impl<T: Clone + 'static> FnOnce<()> for NodeRef<T> {
|
||||
type Output = Option<T>;
|
||||
|
||||
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl FnMut<()> for NodeRef {
|
||||
impl<T: Clone + 'static> FnMut<()> for NodeRef<T> {
|
||||
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl Fn<()> for NodeRef {
|
||||
impl<T: Clone + 'static> Fn<()> for NodeRef<T> {
|
||||
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue