Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions nicegui/elements/sub_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ def add(self, path: str, page: Callable) -> Self:
self._show()
return self

def refresh(self) -> None:
"""Rebuild this sub pages element.
*Added in version 3.1.0*
"""
self._reset_match()
self._show()

def _show(self) -> None:
"""Display the page matching the current URL path."""
self._rendered_path = ''
Expand Down
13 changes: 13 additions & 0 deletions nicegui/sub_pages_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ def on_path_changed(self, handler: Callable[[str], None]) -> None:
"""
self._path_changed_handlers.append(handler)

async def refresh(self) -> None:
"""Refresh the currently shown sub pages.
This will clear and rebuild the current sub page as if navigating to it again.
Useful when you want to update the page content based on changes in data or state.
*Added in version 3.1.0*
"""
for el in context.client.layout.descendants():
if isinstance(el, SubPages):
el._reset_match() # pylint: disable=protected-access
await self._handle_open(self.current_path)

async def _handle_open(self, path: str) -> bool:
self.current_path = path
self.is_initial_request = False
Expand Down
43 changes: 43 additions & 0 deletions tests/test_sub_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -1169,3 +1169,46 @@ def index():
screen.click('Delete')
screen.wait(0.5)
screen.should_not_contain('main page')


def test_refresh_sub_page(screen: Screen):
calls = {'index': 0, 'outer': 0, 'inner_main': 0, 'inner_other': 0}

@ui.page('/')
@ui.page('/{_:path}')
def index():
calls['index'] += 1
sub_pages = ui.sub_pages({'/': outer_page})
ui.button('Refresh via Router', on_click=ui.context.client.sub_pages_router.refresh)
ui.button('Refresh via SubPages', on_click=sub_pages.refresh)

def outer_page():
calls['outer'] += 1
ui.sub_pages({'/': inner_main, '/other': inner_other})
ui.link('Go to other', '/other')

def inner_main(args: PageArguments):
calls['inner_main'] += 1
ui.button('Refresh inner main', on_click=args.frame.refresh)

def inner_other(args: PageArguments):
calls['inner_other'] += 1
ui.button('Refresh inner other', on_click=args.frame.refresh)

screen.open('/')
assert calls == {'index': 1, 'outer': 1, 'inner_main': 1, 'inner_other': 0}

screen.click('Refresh inner main')
assert calls == {'index': 1, 'outer': 1, 'inner_main': 2, 'inner_other': 0}

screen.click('Go to other')
assert calls == {'index': 1, 'outer': 1, 'inner_main': 2, 'inner_other': 1}

screen.click('Refresh inner other')
assert calls == {'index': 1, 'outer': 1, 'inner_main': 2, 'inner_other': 2}

screen.click('Refresh via Router')
assert calls == {'index': 1, 'outer': 2, 'inner_main': 2, 'inner_other': 3}

screen.click('Refresh via SubPages')
assert calls == {'index': 1, 'outer': 3, 'inner_main': 2, 'inner_other': 4}