I'm new to Yew and Rust, I wanted to write a component that would emit a canvas and pre-initialise it:
use yew;
use web_sys;
#[yew::function_component(App)]
fn app() -> yew::Html {
yew::html!{ <canvas id="main" onload={yew::Callback::from(|_| {
web_sys::console::log_1(&"Hello, World".into());
})}></canvas> }
}
fn main() {
yew::start_app::<App>();
}
However the event is never actually emitted and it's not even defined as the onload property of the canvas in the actual rendered DOM, and I don't understand why.
I tried to rewrite the way the callback is registered by tying it to the window instead of the component:
use yew;
use web_sys;
use wasm_bindgen::{closure::Closure, UnwrapThrowExt};
#[yew::function_component(App)]
fn app() -> yew::Html {
web_sys::window()
.expect_throw("global window must be set")
.set_onload(Some(&Closure::<dyn Fn(web_sys::Event)>::new(|_| {
web_sys::console::log_1(&"Hello, World".into());
}).into_js_value().into()));
yew::html!{ <canvas id="main"></canvas> }
}
fn main() {
yew::start_app::<App>();
}
Now the callback is present in the window.onload property, but it's still never called. Any help with this would be appreciated.
Related
Is there a way to render the PrimeFaces <p:focus> component (or let it do its job) only when the browser window has a certain size? To do this I understand that maybe I have to have access the browser window size in server code and use the component rendered attribute to access this code.
In client code, I get the window width with code like this: $(window).width() > 480.
The reason for this is that I don't want to focus the first component in mobile devices, which most of the time have small screens.
Today I'm doing this with the client code below, but I'd like to use the <p:focus> component for the task, as it also has the benefit to focus the first invalid component when validation fails.
$(
function()
{
if (bigWindow())
{
focusFirstInput();
}
}
)
function bigWindow()
{
return $(window).width() > 480;
}
function focusFirstInput()
{
$("#form input:text, #form input[type=number], #form input[type=password], #form textarea").
first().focus();
}
I've found a way using the <p:focus> component:
$(
function()
{
let primeFacesOriginalFocusFunction = PrimeFaces.focus;
PrimeFaces.focus =
function(id, context)
{
if (!isMobile())
{
primeFacesOriginalFocusFunction(id, context);
}
}
}
)
function isMobile()
{
return ...
}
I am having issues with handling drag and drop. I prevent_default on my drop target for both the dragEnter and dragOver events, which I can verify are firing, but the drop event is never triggered. I have also tried setting the dataTransfer.dropEffect property, which has no effect.
use yew::prelude::*;
use web_sys::{DragEvent, console::log_1};
#[function_component(App)]
pub fn app() -> Html {
let ondragenter = Callback::from(|e: DragEvent| {
e.prevent_default();
e.data_transfer().unwrap().set_drop_effect("move"); // optional
log_1(&"enter".into());
});
let ondragover = Callback::from(|e: DragEvent| {
e.prevent_default();
log_1(&"over".into());
});
let ondrop = Callback::from(|e: DragEvent| {
log_1(&"drop".into());
});
html! {
<main style="position: absolute; top: 0; bottom: 0; left: 0; right: 0;"
{ondragenter}
{ondragover}
{ondrop}>
</main>
}
}
with web_sys's DragEvent and DataTransfer features enabled.
I am running this using Tauri and have tried with Yew v. 0.19 and 0.20.
I am trying to pass a function as property inside a component in Vue3. Here is the code:
// ExampleComponent.vue
<template>
Here goes component content...
</template>
<script>
export default {
name: ''
}
</script>
<script setup>
import { onMounted } from "vue"
const props = defineProps({
onLoad: {
type: Function,
default() {
return {}
}
}
})
onMounted(() => {
if (props.onLoad) { // This doesn't work and passes every time
props.onLoad()
}
})
</script>
Here is the parent component calling child ExampleComponent.vue. It may or may not pass the onLoad function.
<ExampleComponent \>
What I want is that call this function only if the property on-load is passed? Is there a way in Vue3 to check if the property is passed explicitly?
you can use watcheffect :
javascript
watchEffect(() => {
if(props.onLoad) props.onLoad()
});
once '''onLoad''' value changed, it will tigger.
How can I make a gtk4::Box clickable in gtk_rs?
In GTK3 it seems that using an EventBox was the way to achieve this, however in GTK4:
Stop using GtkEventBox
GtkEventBox is no longer needed and has been removed.
All widgets receive all events.
https://docs.gtk.org/gtk4/migrating-3to4.html#stop-using-gtkeventbox
So it seems that click handlers should now be attached to widgets directly. However I can't find any clear documentation or examples on how to do this.
If someone could give me an example of attaching a click listener to a gtk4::Box it would be much appreciated.
You can do this using gtk::GestureClick like shown in this example.
Here is a full example (click somewhere inside the window as the box is not actually visible):
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow};
fn main() {
// Create a new application
let app = Application::builder()
.application_id("org.gtk-rs.example")
.build();
// Connect to "activate" signal of `app`
app.connect_activate(|app| {
build_ui(app);
});
// Run the application
app.run();
}
fn build_ui(app: &Application) {
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("My GTK App")
.build();
// Create a box
let gtk_box = gtk::builders::BoxBuilder::new()
.height_request(200)
.width_request(300)
.build();
// Assign a click listener
let gesture = gtk::GestureClick::new();
gesture.connect_released(|gesture, _, _, _| {
gesture.set_state(gtk::EventSequenceState::Claimed);
println!("Box pressed!");
});
gtk_box.add_controller(&gesture);
// Add the box
window.set_child(Some(>k_box));
// Present window to the user
window.present();
}
A more involved example
Say you wanted to actually also see the box and maybe provide some user feedback on mouse hover. Then you will need to use CSS rules to achieve that.
Change your main.rs to:
use gtk::gdk::Display;
use gtk::{CssProvider, StyleContext, prelude::*};
use gtk::{Application, ApplicationWindow};
fn main() {
// Create a new application
let app = Application::builder()
.application_id("org.gtk-rs.example")
.build();
// Connect to "activate" signal of `app`
app.connect_activate(|app| {
// Load a CSS stylesheet from the included bytes.
let provider = CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
// Give the CssProvider to the default screen so the CSS rules are
// applied to the window.
StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing gtk css provider."),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
build_ui(app);
});
// Run the application
app.run();
}
fn build_ui(app: &Application) {
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("My GTK App")
.build();
// Create a box
let gtk_box = gtk::builders::BoxBuilder::new()
.height_request(200)
.width_request(300)
.margin_bottom(20)
.margin_end(20)
.margin_start(20)
.margin_top(20)
.css_classes(vec![String::from("hover-box")])
.build();
// Assign a click listener
let gesture = gtk::GestureClick::new();
gesture.connect_released(|gesture, _, _, _| {
gesture.set_state(gtk::EventSequenceState::Claimed);
println!("Box pressed!");
});
gtk_box.add_controller(&gesture);
// Add the box
window.set_child(Some(>k_box));
// Present window to the user
window.present();
}
and create a style.css file in the src/ directory (the same directory where the main.rs is located) with this content:
.hover-box {
background-color: blue;
border-radius: 5px;
}
.hover-box:hover {
background-color: rgb(11, 133, 240);
border-radius: 5px;
}
Now you get a gtk4::Box with a 5px border radius and blue background color that changes when you hover the mouse above the box.
i am trying to clear my Textinput focus inside keyboard hide event,but i am not able to get reference
inside keyboard hide event method.i tried to print props value it also getting undefined
constructor (props) {
this.inputs = {};
}
_keyboardDidHide () {
console.log("value"+this.props);
this.inputs['inputValue'].blur();
}
componentWillMount () {
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
}
componentWillUnmount () {
this.keyboardDidHideListener.remove();
}
<TextInput
ref={input => {
this.inputs['inputValue'] = input;
}}
autoFocus={true}
blurOnSubmit={false}
/>
let me know how to clear the TextInput focus on _keyboardDidHide method.
I'm not 100% sure what you're trying to do here, however I assume you want to at least get the info out from your input.
No need for that ref magic there though, just use simple react state changes.
class InputWrapper extends React.Component {
constructor() {
super();
this.state = {
input: ''
};
this.handleInput = this.handleInput.bind(this);
}
handleInput(input) {
this.setState({input});
}
render() {
return (
<TextInput onChangeText={this.handleInput} />
);
}
}
This will give you a TextInput Component with control over the input.
Now you should add a componentDidUpdate method as well, that prints out the current state, so you can observe what is happening when you change the input value.
componentDidUpdate() {
console.log(this.state);
}
As for bluring and such, you should definitely check out the documentation on TextInput : https://facebook.github.io/react-native/docs/textinput.html
Additionally, might I suggest to jump into the lifecycle documentation of react itself, plus checking up on props vs state in react. It is a confusing concept in the beginning and you should definitely revisit it.
As for blurring the input, simply do this:
<TextInput
ref={input => this.input = input}
/>
And then you can call:
this.input.blur();
wherever you want.
Also, do not forget to bind your _keyboardDidHide callback within your constructor or when adding it as the listener callback, like so
this._keyboardDidHide = this._keyboardDidHide.bind(this)
Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
Hope this helps