refreshable_documentation.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. from nicegui import ui
  2. from . import doc
  3. @doc.demo(ui.refreshable)
  4. def main_demo() -> None:
  5. import random
  6. numbers = []
  7. @ui.refreshable
  8. def number_ui() -> None:
  9. ui.label(', '.join(str(n) for n in sorted(numbers)))
  10. def add_number() -> None:
  11. numbers.append(random.randint(0, 100))
  12. number_ui.refresh()
  13. number_ui()
  14. ui.button('Add random number', on_click=add_number)
  15. @doc.demo('Refreshable UI with parameters', '''
  16. Here is a demo of how to use the refreshable decorator to create a UI that can be refreshed with different parameters.
  17. ''')
  18. def refreshable_with_parameters():
  19. from datetime import datetime
  20. import pytz
  21. @ui.refreshable
  22. def clock_ui(timezone: str):
  23. ui.label(f'Current time in {timezone}:')
  24. ui.label(datetime.now(tz=pytz.timezone(timezone)).strftime('%H:%M:%S'))
  25. clock_ui('Europe/Berlin')
  26. ui.button('Refresh', on_click=clock_ui.refresh)
  27. ui.button('Refresh for New York', on_click=lambda: clock_ui.refresh('America/New_York'))
  28. ui.button('Refresh for Tokyo', on_click=lambda: clock_ui.refresh('Asia/Tokyo'))
  29. @doc.demo('Refreshable UI for input validation', '''
  30. Here is a demo of how to use the refreshable decorator to give feedback about the validity of user input.
  31. ''')
  32. def input_validation():
  33. import re
  34. pwd = ui.input('Password', password=True, on_change=lambda: show_info.refresh())
  35. rules = {
  36. 'Lowercase letter': lambda s: re.search(r'[a-z]', s),
  37. 'Uppercase letter': lambda s: re.search(r'[A-Z]', s),
  38. 'Digit': lambda s: re.search(r'\d', s),
  39. 'Special character': lambda s: re.search(r"[!@#$%^&*(),.?':{}|<>]", s),
  40. 'min. 8 characters': lambda s: len(s) >= 8,
  41. }
  42. @ui.refreshable
  43. def show_info():
  44. for rule, check in rules.items():
  45. with ui.row().classes('items-center gap-2'):
  46. if check(pwd.value or ''):
  47. ui.icon('done', color='green')
  48. ui.label(rule).classes('text-xs text-green strike-through')
  49. else:
  50. ui.icon('radio_button_unchecked', color='red')
  51. ui.label(rule).classes('text-xs text-red')
  52. show_info()
  53. @doc.demo('Refreshable UI with reactive state', '''
  54. You can create reactive state variables with the `ui.state` function, like `count` and `color` in this demo.
  55. They can be used like normal variables for creating UI elements like the `ui.label`.
  56. Their corresponding setter functions can be used to set new values, which will automatically refresh the UI.
  57. ''')
  58. def reactive_state():
  59. @ui.refreshable
  60. def counter(name: str):
  61. with ui.card():
  62. count, set_count = ui.state(0)
  63. color, set_color = ui.state('black')
  64. ui.label(f'{name} = {count}').classes(f'text-{color}')
  65. ui.button(f'{name} += 1', on_click=lambda: set_count(count + 1))
  66. ui.select(['black', 'red', 'green', 'blue'],
  67. value=color, on_change=lambda e: set_color(e.value))
  68. with ui.row():
  69. counter('A')
  70. counter('B')
  71. @doc.demo('Global scope', '''
  72. When defining a refreshable function in the global scope,
  73. every refreshable UI that is created by calling this function will share the same state.
  74. In this demo, `time()` will show the current date and time.
  75. When opening the page in a new tab, _both_ tabs will be updated simultaneously when clicking the "Refresh" button.
  76. See the "local scope" demos below for a way to create independent refreshable UIs instead.
  77. ''')
  78. def global_scope():
  79. from datetime import datetime
  80. @ui.refreshable
  81. def time():
  82. ui.label(f'Time: {datetime.now()}')
  83. @ui.page('/global_refreshable')
  84. def demo():
  85. time()
  86. ui.button('Refresh', on_click=time.refresh)
  87. ui.link('Open demo', demo)
  88. # END OF DEMO
  89. ui.label('Note: This demo may not work as expected on nicegui.io due to load balancing across multiple servers. '
  90. 'For accurate results, please run this example locally on your machine.').classes('text-gray-600')
  91. @doc.demo('Local scope (variant A)', '''
  92. When defining a refreshable function in a local scope,
  93. refreshable UI that is created by calling this function will refresh independently.
  94. In contrast to the "global scope" demo,
  95. the time will be updated only in the tab where the "Refresh" button was clicked.
  96. ''')
  97. def local_scope_a():
  98. from datetime import datetime
  99. @ui.page('/local_refreshable_a')
  100. def demo():
  101. @ui.refreshable
  102. def time():
  103. ui.label(f'Time: {datetime.now()}')
  104. time()
  105. ui.button('Refresh', on_click=time.refresh)
  106. ui.link('Open demo', demo)
  107. @doc.demo('Local scope (variant B)', '''
  108. In order to define refreshable UIs with local state outside of page functions,
  109. you can, e.g., define a class with a refreshable method.
  110. This way, you can create multiple instances of the class with independent state,
  111. because the `ui.refreshable` decorator acts on the class instance rather than the class itself.
  112. ''')
  113. def local_scope_b():
  114. from datetime import datetime
  115. class Clock:
  116. @ui.refreshable_method
  117. def time(self):
  118. ui.label(f'Time: {datetime.now()}')
  119. @ui.page('/local_refreshable_b')
  120. def demo():
  121. clock = Clock()
  122. clock.time()
  123. ui.button('Refresh', on_click=clock.time.refresh)
  124. ui.link('Open demo', demo)
  125. @doc.demo('Local scope (variant C)', '''
  126. As an alternative to the class definition shown above, you can also define the UI function in global scope,
  127. but apply the `ui.refreshable` decorator inside the page function.
  128. This way the refreshable UI will refresh independently.
  129. ''')
  130. def local_scope_c():
  131. from datetime import datetime
  132. def time():
  133. ui.label(f'Time: {datetime.now()}')
  134. @ui.page('/local_refreshable_c')
  135. def demo():
  136. refreshable_time = ui.refreshable(time)
  137. refreshable_time()
  138. ui.button('Refresh', on_click=refreshable_time.refresh)
  139. ui.link('Open demo', demo)
  140. doc.reference(ui.refreshable)