router.py 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. from typing import Callable, Dict, Union
  2. from nicegui import background_tasks, helpers, ui
  3. class RouterFrame(ui.element, component='router_frame.js'):
  4. pass
  5. class Router:
  6. def __init__(self) -> None:
  7. self.routes: Dict[str, Callable] = {}
  8. self.content: ui.element = None
  9. def add(self, path: str):
  10. def decorator(func: Callable):
  11. self.routes[path] = func
  12. return func
  13. return decorator
  14. def open(self, target: Union[Callable, str]) -> None:
  15. if isinstance(target, str):
  16. path = target
  17. builder = self.routes[target]
  18. else:
  19. path = {v: k for k, v in self.routes.items()}[target]
  20. builder = target
  21. async def build() -> None:
  22. with self.content:
  23. ui.run_javascript(f'''
  24. if (window.location.pathname !== "{path}") {{
  25. history.pushState({{page: "{path}"}}, "", "{path}");
  26. }}
  27. ''')
  28. result = builder()
  29. if helpers.is_coroutine_function(builder):
  30. await result
  31. self.content.clear()
  32. background_tasks.create(build())
  33. def frame(self) -> ui.element:
  34. self.content = RouterFrame().on('open', lambda e: self.open(e.args))
  35. return self.content