Skip to content

ViewChild derive doesn't expose root V::Element, blocking cross-component element passing #112

Description

@schell

Problem

Components using #[derive(ViewChild)] have a #[child] field that is a V::Element, but there's no way to access it from outside the component. The derive only implements as_append_arg() which yields V::Nodes for DOM insertion — it doesn't expose the element itself.

This means if component A needs to pass its root element to component B's API (e.g. for positioning, measurement, or imperative DOM operations), there's no generic way to do it.

Concrete scenario

A Floaty overlay component has a method:

pub async fn trigger_floating(&self, target: &V::Element, dx: f64, dy: f64)

This works fine when you have a raw V::Element (e.g. created via rsx!). But when the target is another component — like a Button<V> or an Icon<V> — there's no way to get its underlying V::Element:

let button = Button::new("Save", None);
// button.element()  // <- doesn't exist, #[child] field is private
floaty.trigger_floating(&button.???, 0.0, 0.0).await;

The workaround is wrapping the component in a <span> and using that span's V::Element instead. That works but is clunky and loses the exact element position.

The deeper issue

ViewChild is implemented for V::Element, V::Text, and V::Node. Text nodes aren't elements, so fn element(&self) -> &V::Element can't live on ViewChild itself. A separate trait (or a conditional implementation) is needed for components whose #[child] field is specifically a V::Element.

Additionally, there's no generic way to obtain document.body (or any existing DOM node) as a V::Element. mogwai::web::body() returns web_sys::HtmlElement, which is a concrete Web-view type, not a generic V::Element. This forces downstream code to either use workarounds (mouse coordinates instead of elements) or abandon genericity over V.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions