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

Complex Layout with multiple "set of children" #870

Open
JovanVeljanoski opened this issue Nov 23, 2024 · 3 comments
Open

Complex Layout with multiple "set of children" #870

JovanVeljanoski opened this issue Nov 23, 2024 · 3 comments

Comments

@JovanVeljanoski
Copy link
Collaborator

Hi,

I need to create a more complex layout, that requires passing different children (component) to different parts (components) of the layout. I have made this simple pycafe example illustrating what my intention is: I want to pass a component to the "Left" part of the layout, and a different component to the "right" part of the Layout.

Here is the pycafe example

Currently, the component passed to the layout is used in both the "Left" and "Right" side of the layout. I would like essentially to be able to pass (in whatever way) the Left and Right component to be on the same page.

What I tried:

  • I naively thought I can pass a list of components to the Router object, and then select the relevant stuff inside the layout component. That does not work as a Div class is recieved by the time data arrives in the Layout class/component.

My current understanding (looking at the Layout documentation and the few layout implementations of solara) is that there is a single Div (child?) that is passed to the layout. Is there a way we can interface to that, or otherwise intercept it to allow for different type of input (say multiple components?).

I hope the question is clear, if not I would be happy to elaborate. Thank you!!

@JovanVeljanoski
Copy link
Collaborator Author

Hi again,

After some digging into the solara repo, I have two potential approaches, on how proceed with the question above:

  1. NoLayout + Fully custom "Wrapper" Layout component.
    This is inspired by the layout howto in the documentation.
    There we learn that we can.. kind of "erase" the layout by simple having the following as a layout:
@solara.component
def Layout(children=[]):
    # there will only be 1 child, which is the Page()
    return children[0]

Then we could define a custom "Wrapper" component, something like

@solara.component
WrapperLayout(side_panel=None, main_panel=None):
   ....

The above would define the whole layout. Then we can just pass components do this wrapper component, and combined with the "empty" layout above, it should do the trick.

I am not sure if this approach is valid.. At first I thought that there is another "layer" through with the WrapperLayout will pass through, (the "no" Layout defined above), and I do not know (have not checked yet) if that will interfere with styling and the like (as I am doing quite some heavy styling on.. everything).

  1. Steal the idea behind AppLayout.
    This.. well I don't quite understand it, but I essentially followed what is done here.

More easily shown as a pycafe example

What I do not like about this.. is well I do not quite understand how it works, and whether it is an appropriate approach to be used with many routes and many simultanious users. But I "understand" it enough to adopt it for my usecase and make a "complex" layout that can be filled with various components (which was the original quest).

I would very much appreciate some pointers in which of the two approaches above is recommended for use with solara (if any!), or and I approaching this in an entirely wrong manner.

Thank you - I hope this makes sense.

P.S.: As I said, I do not understand this ElementPortal thing.. but if it does what I think it does .. - super cool!! (provided it is stable to be (ab)used).

@maartenbreddels
Copy link
Contributor

  • I naively thought I can pass a list of components to the Router object, and then select the relevant stuff inside the layout component. That does not work as a Div class is recieved by the time data arrives in the Layout class/component.

That might actually container your children, but indeed there might be an extra Div around it, which you saw. It is probably this Div

If you print out the children of a Layout, you should see:

[Div(classes = ['solara-autorouter-content'], children = ...)]

In the case of your above PyCafe app:

print(children, children[0].kwargs["children"])

will print out:

[Div(classes = ['solara-autorouter-content'], children = ...)] [Title('Lexilingo: Home'), Left()]
  1. NoLayout + Fully custom "Wrapper" Layout component.

Yes, perfectly valid, you'd need to do a bit of work to handle routing yourself, but not a bad idea.

2. Steal the idea behind AppLayout.

Also valid, the ElementPortal is not a public API, but we tend not to break things 'just because', and although I can not make promises, it's unlikely to be broken in the future.

This portal was needed to support a 'streamlit-style' sidebar, which makes it easier to people to switch from streamlit.

I think 1 is easier to read/understand. 2. is a bit more easy to use, at the cost of some hidden complexity/magic. Feel free to pick you poison :)

Let me know if anything is still unclear.

@JovanVeljanoski
Copy link
Collaborator Author

Hi!
Thanks for the explanation! It makes perfect sense.

I think option 2 is magic i've never seen before,and so powerful..allows for some crazy things. Scary to use since it is not public, but maybe you should consider making it if it is stable enough.

Thanks!

(Feel free to close this)

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

No branches or pull requests

2 participants