question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature request] Allow the list of child widgets of a UserControl to be modified at runtime

See original GitHub issue

Hi, currently it seems that UserWidgets cannot really alter its content after its initial creation - which kind of forces any sort of dynamic attributes in the UI to rely entirely on the predefined Flutter widgets that Flet ships with - which in its turn limits or adds complexity to how and what sort of interactive/dynamic UI you can build with Flet.

So could we have the ability to modify this list at runtime, perhaps by letting you manually call the build method once more after the initial creation of the widget?

Example usecases could be to enable users to implement features like https://github.com/flet-dev/flet/issues/590 directly in Flet only by combining existing widgets, arguably a tree view in particular could perhaps be created by just appending elements to a series of columns at runtime as done in the To-Do list example app, but this would require additional code compared to that if one could simply re-run the build method or in some other way re-create the entire list of child widgets of the UserControl.

To give you a taste of how a dynamic widget could look like:

class FlexGrid(flet.UserControl):
    def __init__(self,
        controls: list[Control] = None,
        max_columns: int = 2,
        spacing_between_items_vertical: typing.Optional[int] = 10,
        spacing_between_items_horizontal: typing.Optional[int] = 10, 
        flow_direction: types.FlowDirection = types.FlowDirection.HORIZONTALLY,
        tooltip: str = "",
        ref: flet.Ref = None, width: OptionalNumber = None, height: OptionalNumber = None, left: OptionalNumber = None, top: OptionalNumber = None, right: OptionalNumber = None, bottom: OptionalNumber = None, expand: typing.Union[None, bool, int] = None, opacity: OptionalNumber = None, rotate: RotateValue = None, scale: ScaleValue = None, offset: OffsetValue = None, animate_opacity: AnimationValue = None, animate_size: AnimationValue = None, animate_position: AnimationValue = None, animate_rotation: AnimationValue = None, animate_scale: AnimationValue = None, animate_offset: AnimationValue = None, visible: typing.Optional[bool] = None, disabled: typing.Optional[bool] = None, data: typing.Any = None, clip_behavior: ClipBehavior = None
    ):
        super().__init__(controls, ref, width, height, left, top, right, bottom, expand, opacity, rotate, scale, offset, animate_opacity, animate_size, animate_position, animate_rotation, animate_scale, animate_offset, visible, disabled, data, clip_behavior)
        
        self.tooltip = tooltip
        self.controls = controls
        self.max_columns = max_columns
        self.spacing_between_items_vertical = spacing_between_items_vertical
        self.spacing_between_items_horizontal = spacing_between_items_horizontal
        self.flow_direction = flow_direction
        
        
    def build(self):
        i = -1
        rows: list[flet.Row] = []
        for control in self.controls:
            i += 1
            currentColumnNumber = i % self.max_columns          # 0 based
            currentRowNumber = math.floor(i / self.max_columns) # 0 based
            if currentColumnNumber == 0:
                # print("yes")
                
                row = flet.Row() if self.flow_direction == types.FlowDirection.HORIZONTALLY else flet.Column()
                row.vertical_alignment="start"
                row.horizontal_alignment="start"
                if self.tooltip:
                    row.tooltip = self.tooltip
                row.spacing = self.spacing_between_items_horizontal if self.flow_direction == types.FlowDirection.HORIZONTALLY else self.spacing_between_items_vertical
                
                rows.append(row)

            
            rows[-1].controls.append(control)
            

        column = flet.Row(controls=rows) if self.flow_direction != types.FlowDirection.HORIZONTALLY else flet.Column(controls=rows)
        column.spacing = self.spacing_between_items_horizontal if self.flow_direction != types.FlowDirection.HORIZONTALLY else self.spacing_between_items_vertical
        column.vertical_alignment="start"
        column.horizontal_alignment="start"
        
        # column.width = self.page.width
        return column

The above code is really everything you would need to create a custom grid layout in Python with the existing tools in Flet. In fact the above code works as is (you can instanciate FlexGrid & give it a list of child controls in its constructor and it will just work), but for it to be dynamic one would also need to be able to again re-run the build method (which is what Im hoping to become a reality with this feature request). However in order to make this “dynamic” with the existing tools, one would need to start digging in the UserControls child tree and start to manually append items to all the rows and columns in there (which would lead to a lot of extra code complexity).

Thanks for reading ❤️

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
FeodorFitsnercommented, Nov 22, 2022

OK, I see. We are going to work on “reactive” approach for DataTable implementation. I have some ideas how to do that.

1reaction
FeodorFitsnercommented, Nov 21, 2022

It is possible to implement TreeView with existing Flet. Take a look at “Collapsible” and “ManuItem” controls I made for Gallery app: https://github.com/flet-dev/gallery/blob/v1/main.py

I’m sure you can easily adapt the idea of collapsible to a tree (collapsible inside collapsible).

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Find Children of a UserControl instead of a Window
I have successfully replaced my main Window with a User Control that implements almost exactly the same functionality as the Main Window. Replacing...
Read more >
WPF Add UserControl at Runtime - YouTube
Code underhttps://codedocu.com/Details?d=1809&a=9&f=271&l=0&v=d&t=WPF:-Load- UserControl -at-runtimeC#, WPF Code ...
Read more >
How to: Add to or Remove from a Collection of Controls at Run ...
Learn how to add controls to and remove controls from any container control on your forms, such as the Panel or GroupBox control, ......
Read more >
Frame phrase - Progress Documentation
Specifies whether the following field-level widgets in the frame inherit the frame's foreground color: BROWSE, COMBO-BOX (all types), EDITOR, FILL-IN (NATIVE ...
Read more >
WPF Control Development Unleashed: Building Advanced ...
Controls derived from ContentControl are used to represent individual items that are displayed within list-based controls such as a ListBox, ItemsControl, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found