Is there any way to make DOM action via use_node_ref
? or alternatively, how to do document.query_selector()
in Rust using yew?
use web_sys::HtmlInputElement;
use yew::{
function_component, functional::*, html,
NodeRef, Html
};
#[function_component(UseRef)]
pub fn ref_hook() -> Html {
let input_ref = use_node_ref();
let all_editables = input_ref.query_selector("[contenteditable]")
web_sys::console::(all_editables)
html! {
<div>
<input ref={input_ref} type="number" />
</div>
}
}
Goal: I have a rich text editor app. And I have a minified html in form of string like this <h1> this is title</h1><p>hello world</>
and I need to get the DOM and change the innerHTML
to set it to this value.
Goal2: I will also need to update the innerHtml
as the user write things in the contenteditable
elements. Fore example when the user type @john smith
I will make a create an <a>
element with href
the have the link to John smith
's profile.
Many things to tackle with your question.
More to read about this in Alternative for innerHTML?
But instead create text nodes. So using web-sys you would do something like:
let txtNode: Node = window()
.unwrap_throw()
.document()
.unwrap_throw()
.create_text_node("Hello")
.dyn_into()
.unwrap_throw();
myDomElement.append_hild(&txtNode).unwrap_throw();
There are many ways to do this so ill just show you one of them - controlled input
core idea is keep your input value in use_state
and sync it with the input element using value
and oninput
attributes.
#[function_component(ControlledInputComponent)]
pub fn controlled_input_component() -> Html {
let my_text_handle = use_state(|| "".to_string());
let my_text = (*my_text_handle).clone();
let handle_input = Callback::from(move |input_event: InputEvent| {
let event: Event = input_event.dyn_into().unwrap_throw();
let input_elem: HTMLInputElement = event.target().unwrap_throw().dyn_into().unwrap_throw();
let value = input_elem.value();
my_text_handle.set(value); // update as user types
});
html! {
<div>
<input type="text" value={my_text} oninput={handle_input} />
</div>
}
}
**External to yew as you should generally avoid updating DOM that is controlled by yew
You can then use use_effec_with_deps
to react to your input changing and update your external preview there
let my_text_handle = use_state(|| "".to_string());
let my_text = (*my_text_handle).clone();
use_effect_with_deps(move |my_text| {
// run all the code from my tip #1 like:
// myDomElement.append_hild(&txtNode).unwrap_throw();
||{}
}, my_text);