xilem_web: An example using AnyDomView would be super helpful
I'm trying to make a <li> which can have one of two types, either a button or text node, depending on the state.
I tried to do something like:
fn bar(state: &mut bool) -> impl HtmlLiElement<State> {
html::li(if *state {
Box::new(html::button("button")) as Box<AnyDomView<State>>
} else {
Box::new("not a button") as Box<AnyDomView<State>>
})
}
But got a bunch of errors:
rustc output
Checking library-viewer v0.0.0 (/Users/rodarmor/src/gossamer/crates/library-viewer)
error: could not compile `library-viewer` (bin "library-viewer") due to 3 previous errors; 3 warnings emitted
error[E0277]: the trait bound `ViewCtx: OrphanView<&'static str, State, ()>` is not satisfied
--> crates/library-viewer/src/main.rs:117:5
|
117 | Box::new("not a button") as Box<AnyDomView<State>>
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `OrphanView<&'static str, State, ()>` is not implemented for `ViewCtx`, which is required by `&str: AnyView<State, (), ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>>`
|
= help: the following other types implement trait `OrphanView<V, State, Action, Message>`:
<ViewCtx as OrphanView<&'static str, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<BezPath, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<Cow<'static, str>, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<f32, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<f64, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<i16, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<i32, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
<ViewCtx as OrphanView<i64, State, Action, Box<(dyn xilem_web::Message + 'static)>>>
and 12 others
= note: required for `&str` to implement `View<State, (), ViewCtx>`
= note: required for `&str` to implement `AnyView<State, (), ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>>`
= note: required for the cast from `Box<&str>` to `Box<(dyn AnyView<State, (), ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>> + 'static)>`
error[E0277]: the trait bound `Box<dyn AnyView<State, (), ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>>>: ViewSequence<_, _, ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>, _, Box<(dyn xilem_web::Message + 'static)>>` is not satisfied
--> crates/library-viewer/src/main.rs:114:12
|
114 | html::li(if *state {
| ___--------_^
| | |
| | required by a bound introduced by this call
115 | | Box::new(html::button("button")) as Box<AnyDomView<State>>
116 | | } else {
117 | | Box::new("not a button") as Box<AnyDomView<State>>
118 | | })
| |___^ the trait `ViewSequence<_, _, ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>, _, Box<(dyn xilem_web::Message + 'static)>>` is not implemented for `Box<dyn AnyView<State, (), ViewCtx, Pod<DynNode, Box<(dyn Any + 'static)>>>>`
|
= help: the following other types implement trait `ViewSequence<State, Action, Context, Element, Marker, Message>`:
<() as ViewSequence<State, Action, Context, Element, (), Message>>
<(Seq,) as ViewSequence<State, Action, Context, Element, (Marker,), Message>>
<(Seq0, Seq1) as ViewSequence<State, Action, Context, Element, (M0, M1), Message>>
<(Seq0, Seq1, Seq2) as ViewSequence<State, Action, Context, Element, (M0, M1, M2), Message>>
<(Seq0, Seq1, Seq2, Seq3) as ViewSequence<State, Action, Context, Element, (M0, M1, M2, M3), Message>>
<(Seq0, Seq1, Seq2, Seq3, Seq4) as ViewSequence<State, Action, Context, Element, (M0, M1, M2, M3, M4), Message>>
<(Seq0, Seq1, Seq2, Seq3, Seq4, Seq5) as ViewSequence<State, Action, Context, Element, (M0, M1, M2, M3, M4, M5), Message>>
<(Seq0, Seq1, Seq2, Seq3, Seq4, Seq5, Seq6) as ViewSequence<State, Action, Context, Element, (M0, M1, M2, M3, M4, M5, M6), Message>>
and 12 others
note: required by a bound in `xilem_web::elements::html::li`
--> /Users/rodarmor/src/xilem/xilem_web/src/elements.rs:484:5
|
484 | / define_elements!(
485 | | // the order is copied from
486 | | // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
487 | | // DOM interfaces copied from https://html.spec.whatwg.org/multipage/grouping-content....
... |
516 | | (Li, li, HtmlLiElement),
| | -- required by a bound in this function
... |
606 | | (Template, template, HtmlTemplateElement),
607 | | );
| |_____^ required by this bound in `li`
= note: this error originates in the macro `define_element` which comes from the expansion of the macro `define_elements` (in Nightly builds, run with -Z macro-backtrace for more info)
[Finished running. Exit status: 101]
I took a look at the examples, but didn't find any usage of AnyDomView. Am I trying using AnyDomView in the right way here, or is another approach required?
By the way, so far having a lot of fun with xilem_web, so thanks for putting it out there!
Hmm we really have to work on the error messages...
I just discovered that we don't currently have the .boxed() combinator of xilem, should be added with the fix in #460...
So with that method it would be just html::button("button").boxed() for either of those children. ~~Anyway impl HtmlLiElement is not possible with an AnyDomView, this needs to be either Box<AnyDomView<State>> or impl DomView<State>~~.
You're right, we should probably add a simple example that shows the use of AnyView (and probably also describes the advantages and limitations of it).
In your case an Either would make sense, checkout e.g. the short example of #452, that allows retaining the intersection of the element type (or in other words the common DOM interface of these views).
By the way, so far having a lot of fun with xilem_web, so thanks for putting it out there!
Good to hear :)
Hmm I don't think #460 fixes this, I'll keep it open until we have a small example for AnyDomView...
Anyway impl HtmlLiElement is not possible with an AnyDomView, this needs to be either Box<AnyDomView<State>> or impl DomView<State>.
Whoops forget about that, I missed the li element that's surrounding the view...
Yah my code is definitely wrong 😅
I just tried #460, and it works perfectly. With that PR, my actual code is:
ul(
state
.packages
.iter()
.map(|(hash, manifest)| {
li(
if let Some(handler) = state.handlers.get(&manifest.ty().into()) {
html::button(manifest.name.clone()).boxed()
} else {
manifest.name.clone().boxed()
},
)
})
.collect::<Vec<_>>(),
),
@Philipp-M what's the status of this issue now? You set #460 to not auto-close this, so I presume there must still be follow-up needed?
I wanted to add the AnyDomView somewhere in an example, so that the actual title of this issue is "fixed", maybe a new one generally showing Either/OneOf and AnyDomView and explaining the strengths and weaknesses of each or something like that