Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Few questions on usage #29

Open
milesj opened this issue Oct 15, 2024 · 5 comments
Open

Few questions on usage #29

milesj opened this issue Oct 15, 2024 · 5 comments
Labels
question Further information is requested

Comments

@milesj
Copy link

milesj commented Oct 15, 2024

@ccbrown Just have a few questions so far that I haven't been able to figure out.

1 - How to pass children through for custom components? Maybe we need a Fragment component here?

#[derive(Default, Props)]
pub struct EntryProps<'a> {
    pub title: String,
    pub children: Vec<AnyElement<'a>>,
}

#[component]
pub fn Entry<'a>(props: &EntryProps<'a>) -> impl Into<AnyElement<'static>> {
    element! {
        Box {
            Box(margin_right: 1) {
                Text(content: format!("{}:", props.title))
            }
            Box {
                // What to do here???
                #(props.children.iter())
            }
        }
    }
}

2 - Is it possible to render components as props to other components? Or is it only possible with children?

// This
Box {
    Entry(title: "Root", value: StyledText(content: env.store.dir.to_string_lossy(), style: Style::Path))
}

// Instead of 
Box {
    Entry(title: "Root") {
        StyledText(content: env.store.dir.to_string_lossy(), style: Style::Path)
    }
}
@ccbrown
Copy link
Owner

ccbrown commented Oct 16, 2024

  1. What you have almost works, except props needs to become a mutable reference, and the lifetime of the returned element becomes 'a:
#[component]
pub fn Entry<'a>(props: &mut EntryProps<'a>) -> impl Into<AnyElement<'a>> {
    element! {
        Box {
            Box(margin_right: 1) {
                Text(content: format!("{}:", props.title))
            }
            Box {
                #(&mut props.children)
            }
        }
    }
}
  1. There's nothing particularly special about the props values. Anything you can express in Rust can be passed. So to pass another element, you would need to use the element! macro like so:
#[derive(Default, Props)]
pub struct ExampleProps<'a> {
    pub my_child: Option<AnyElement<'a>>,
}

#[component]
fn Example<'a>(props: &mut ExampleProps<'a>) -> impl Into<AnyElement<'a>> {
    element! {
        Box {
            #(&mut props.my_child)
        }
    }
}

fn main() {
    element! {
        Example(my_child: element! {
            Text(content: "foo")
        }.into_any())
    }
    .print();
}

Or alternatively, if you want to avoid nesting, you can define the child beforehand:

fn main() {
    let my_child = element! {
        Text(content: "foo")
    }
    .into_any();

    element! {
        Example(my_child)
    }
    .print();
}

@ccbrown ccbrown added the question Further information is requested label Oct 16, 2024
@milesj
Copy link
Author

milesj commented Oct 16, 2024

Awesome, got these working, thank you! It would be great of their was an example file with all the different ways things can be done in regards to the syntax.

@milesj
Copy link
Author

milesj commented Dec 5, 2024

For convenience, it would be nice to maybe offer an any_element! macro that just calls element!().into_any() internally. Would help keep the JSX-like syntax a little cleaner.

@milesj
Copy link
Author

milesj commented Dec 8, 2024

Another suggestion, rename Box to View so that it doesn't conflict with Rust's native Box. I've bad to rename this a few times now.

@ccbrown
Copy link
Owner

ccbrown commented Dec 8, 2024

Another suggestion, rename Box to View so that it doesn't conflict with Rust's native Box. I've bad to rename this a few times now.

In hindsight I wish I had done this from the start. But as this would undoubtedly break every program using the library, I would want to wait until I have other big breaking changes to release before making a change like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants