Skip to content

bug: page.show_drawer()/close_drawer() fail under page.render_views() #6413

@FeodorFitsner

Description

@FeodorFitsner

Description

When using the declarative API (page.render_views(Component)), calling page.show_drawer() (and related: close_drawer, show_end_drawer, close_end_drawer) raises a TypeError because self.views is a Component wrapper, not a list[View].

BasePage.__top_view() / __root_view() call len(self.views) directly, which fails with:

TypeError: object of type 'Component' has no len()

After unwrapping the outer Component, when the component returns a single View (not a list), unwrap_component(self.views) returns a View instance — so len(views) still fails with object of type 'View' has no len().

By extension, any page-level accessor backed by __root_view() (e.g. page.appbar, page.drawer, page.navigation_bar, page.controls) is also broken under render_views.

Repro

import flet as ft


@ft.component
def App():
    selected, set_selected = ft.use_state(0)

    pages = [
        ("Home", ft.Icons.HOME_OUTLINED, ft.Icons.HOME),
        ("Store", ft.Icons.STORE_OUTLINED, ft.Icons.STORE),
        ("About", ft.Icons.INFO_OUTLINED, ft.Icons.INFO),
    ]

    async def show_drawer():
        await ft.context.page.show_drawer()

    async def handle_change(e: ft.Event[ft.NavigationDrawer]):
        set_selected(e.control.selected_index)
        await ft.context.page.close_drawer()

    return ft.View(
        appbar=ft.AppBar(
            title=ft.Text(pages[selected][0]),
            leading=ft.IconButton(ft.Icons.MENU, on_click=show_drawer),
        ),
        drawer=ft.NavigationDrawer(
            selected_index=selected,
            on_change=handle_change,
            controls=[
                ft.Container(height=12),
                *[
                    ft.NavigationDrawerDestination(
                        label=label, icon=icon, selected_icon=sel
                    )
                    for label, icon, sel in pages
                ],
            ],
        ),
        controls=[
            ft.SafeArea(
                content=ft.Text(f"Welcome to {pages[selected][0]}", size=24)
            )
        ],
    )


def main(page: ft.Page):
    page.render_views(App)


ft.run(main)

Tap the menu icon in the app bar to trigger the error.

Traceback

File ".../flet/controls/base_page.py", line 476, in show_drawer
    await self.__top_view().show_drawer()
File ".../flet/controls/base_page.py", line 292, in __top_view
    if len(self.views) == 0:
TypeError: object of type 'Component' has no len()

Expected

The drawer opens. __top_view() / __root_view() should resolve component-wrapped views and a single-View return shape.

Environment

  • Flet: main (reproduced on release/v0.85.0)
  • Python 3.13 / macOS

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

🔖 Ready

Relationships

None yet

Development

No branches or pull requests

Issue actions