[Feature request] Allow the list of child widgets of a UserControl to be modified at runtime
See original GitHub issueHi, 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:
- Created 10 months ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
OK, I see. We are going to work on “reactive” approach for DataTable implementation. I have some ideas how to do that.
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).