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.

Add declarative UI model supports?

See original GitHub issue

If UI and business logic share same data and/or data are lists, imperative UI model is really verbose. If I use declarative UI model, following code is enough. But if I use imperative UI model, I need to implement proper setters for all its properties(and repeat rebuild code in setters) and hold reference to ListView or ListView.controls. Thus I need to properly NAME them.

There are only two hard things in Computer Science: cache invalidation and naming things.

class ListSelectionView(UserControl):
    def __init__(self, group: str, values: list[str], types: list[str], selected_index: int | None, on_select: Callable[[int], None], on_selected_click: Callable[[str], None]):
        super().__init__(expand=1)
        self.group = group
        self.values = values
        self.types = types
        self.selected_index = selected_index
        self.on_select = on_select
        self.on_selected_click = on_selected_click

    def build(self):
        def build_item(i: int, value: str, annotation: str, selected: bool):
            if selected:
                def on_click(_):
                    self.on_selected_click(value)
                return Draggable(
                    group=self.group,
                    content=Container(
                        Row([
                            Text(value, size=15),
                            Container(expand=1),
                            Text(annotation, size=15),
                        ]),
                        on_click=on_click,
                        ink=True, padding=5,
                        bgcolor=colors.BLUE_ACCENT,
                    ),
                    content_feedback=CircleAvatar(
                        content=Text(
                            value,
                            size=15,
                            style='labelLarge',
                        ),
                        radius=40, bgcolor=colors.BLUE_ACCENT
                    ),
                )

            def on_click(_):
                self.on_select(i)
            return Container(
                Row([
                    Text(value, size=15),
                    Container(expand=1),
                    Text(annotation, size=15),
                ]),
                on_click=on_click,
                ink=True,
                padding=5,
            )
        return ListView(
            [build_item(i, value, annotation, i == self.selected_index)
             for i, value, annotation in zip(itertools.count(), self.values, self.types)],
            expand=1,
        )

Currently I use following code to emulate declarative UI model:

class FlutterControl(UserControl):
    def build(self):
        self.container = Container(self.construct(), expand=1)
        return self.container

    def construct(self) -> Control | None:
        return None

    def apply(self):
        self.container.content = self.construct()
        self.update()

But it has a problem: rebuilding will reset scrolling position of ListView.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:3
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
YouJiachengcommented, Oct 12, 2022

I know flet is aiming for imperative programming model. It combines smaller “widgets” to ready-to-use “controls” to construct UI with less nesting levels, which is suitable for imperative UI model. But if the use-case is complex, nesting is unavoidable, which is not friendly to imperative UI model – traverse component tree and mutate leaves’s properties is really verbose. I think to have a UserControl with declarative UI model is really helpful: Professional users can construct arbitrary complex custom controls with declarative model, while all users(including professional users) can use ready-to-use controls(both built-in and custom) with straight-forward imperative model.

0reactions
ndonkoHenricommented, Nov 25, 2022

Another idea would be to let the user set an ID attribute on the control.

@skeledrew tried something similar in his Flet CLI(fletil): https://pypi.org/project/fletil/0.3.0/

Read more comments on GitHub >

github_iconTop Results From Across the Web

Declarative vs Imperative UI in Android - Section.io
In this article, we are going to have a look at the two types of UI frameworks, declarative and imperative. We will look...
Read more >
Thinking in Compose | Jetpack Compose - Android Developers
In Compose's declarative approach, widgets are relatively stateless and do not expose setter or getter functions. In fact, widgets are not exposed as...
Read more >
Introduction to declarative UI - Flutter documentation
This introduction describes the conceptual difference between the declarative style used by Flutter, and the imperative style used by many other UI ......
Read more >
The Shift From Imperative to Declarative UI - Increment
In a declarative framework, changes in state trigger a rebuild of the UI, which removes a whole category of state-related bugs and makes...
Read more >
Imperative v Declarative UI Design - Rootstrap
In this article, we will define and compare imperative and declarative UI design and explore the benefits and drawbacks of designing apps ...
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