How to create a view which conditionally selects the child view to show? #485
-
Say that I have a parent view and three possible child views as in the example below. The parent view should conditionally select which child view to show based on the value of The questions are:
enum Thing {
Foo(x, y),
Bar(z),
Baz
}
// relm4 parent view
struct ParentModel {
let thing: Thing
}
#[relm4::component]
impl SimpleComponent for ParentModel {
// ...
}
// relm4 child views
struct FooModel {
x: i32,
y: i32,
}
#[relm4::component]
impl SimpleComponent for FooModel {
// ...
}
struct BarModel {
z: i32,
}
#[relm4::component]
impl SimpleComponent for BarModel {
// ...
}
struct BazModel {}
#[relm4::component]
impl SimpleComponent for BazModel {
// ...
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Probably the
Yes, that shouldn't change anything regarding the initialization of widgets. |
Beta Was this translation helpful? Give feedback.
-
I found that the conditional widgets example in the book produced a compile error, so what I had to do instead was extract the struct ParentModel {
thing: Thing,
// must initialise these in the fn init(...) method
foo: Controller<FooModel>,
bar: Controller<BarModel>,
baz: Controller<BazModel>
} #[relm4::component]
impl SimpleComponent for ParentModel {
view! {
gtk::Box {
append: &self.get_child_widget()
}
}
} impl ParentModel {
fn get_child_widget(&self) -> gtk::Box {
let element = match &self.thing {
Thing::Foo(x, y) => {
let box = gtk::Box::default();
box.set_width_request(...);
box.append(self.foo.widget());
box
}
Thing::Bar(z) => {
let box = gtk::Box::default();
box.append(self.bar.widget());
box
}
Thing::Baz => {
let box = gtk::Box::default();
box.append(self.baz.widget());
box
}
};
// optional: apply any common modifications you'd like to apply to the wrapper for all child views
element.set_hexpand(false);
element
}
} Note that in Also note that this is a bit of a work in progress because I haven't tried wiring up those child views to relay messages in/out yet |
Beta Was this translation helpful? Give feedback.
Sorry for the late reply. Yes, I am actually aware of this behavior and this is a trade-off that was made during the implementation. The way that conditional widgets work currently, everything is initialized. This means that all properties need to be initialized as well and most importunately this initialization needs to be unconditionally. Therefore you can't use variables from destructured fields because Relm4 can't know if they will be available during initialization. Properties with
#[watch]
and#[track]
however will work because they will be updated as soon as their conditional branch is visible and don't need to be initialized upfront.I hope this makes sense to you and this is also…