ex4nicegui 0.6.9__tar.gz → 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/PKG-INFO +223 -48
  2. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/README.md +221 -46
  3. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/dataSourceFacade.py +20 -20
  4. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/index.py +20 -23
  5. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/EChartsComponent/ECharts.py +9 -8
  6. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/__init__.py +14 -0
  7. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/base.py +64 -55
  8. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/mixins/backgroundColor.py +5 -5
  9. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/mixins/disableable.py +8 -8
  10. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/mixins/textColor.py +10 -10
  11. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/aggrid.py +5 -5
  12. ex4nicegui-0.7.1/ex4nicegui/reactive/officials/avatar.py +86 -0
  13. ex4nicegui-0.7.1/ex4nicegui/reactive/officials/badge.py +102 -0
  14. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/button.py +15 -15
  15. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/checkbox.py +6 -7
  16. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/chip.py +6 -7
  17. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/circular_progress.py +7 -7
  18. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/color_picker.py +8 -8
  19. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/column.py +5 -5
  20. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/date.py +6 -6
  21. ex4nicegui-0.7.1/ex4nicegui/reactive/officials/dialog.py +49 -0
  22. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/echarts.py +49 -51
  23. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/expansion.py +6 -6
  24. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/icon.py +7 -13
  25. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/image.py +6 -6
  26. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/input.py +10 -11
  27. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/knob.py +7 -7
  28. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/label.py +11 -9
  29. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/linear_progress.py +7 -7
  30. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/number.py +10 -10
  31. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/radio.py +10 -10
  32. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/row.py +5 -5
  33. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/select.py +11 -10
  34. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/slider.py +6 -6
  35. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/switch.py +6 -7
  36. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/tab.py +0 -12
  37. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/tab_panels.py +5 -5
  38. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/table.py +13 -13
  39. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/tabs.py +5 -5
  40. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/textarea.py +6 -6
  41. ex4nicegui-0.7.1/ex4nicegui/reactive/officials/toggle.py +88 -0
  42. ex4nicegui-0.7.1/ex4nicegui/reactive/officials/tooltip.py +40 -0
  43. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/q_pagination.py +5 -5
  44. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/systems/reactive_system.py +2 -2
  45. ex4nicegui-0.7.1/ex4nicegui/reactive/vfor.js +23 -0
  46. ex4nicegui-0.7.1/ex4nicegui/reactive/vfor.py +268 -0
  47. ex4nicegui-0.7.1/ex4nicegui/reactive/view_model.py +160 -0
  48. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/vmodel.py +42 -12
  49. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/signals.py +23 -21
  50. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/pyproject.toml +2 -2
  51. ex4nicegui-0.6.9/ex4nicegui/reactive/vfor.js +0 -13
  52. ex4nicegui-0.6.9/ex4nicegui/reactive/vfor.py +0 -198
  53. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/LICENSE +0 -0
  54. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/__init__.py +0 -0
  55. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/__init__.py +0 -0
  56. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/dataSource.py +0 -0
  57. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/__init__.py +0 -0
  58. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/containers.py +0 -0
  59. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/layouts.py +0 -0
  60. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/models.py +0 -0
  61. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/text.py +0 -0
  62. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_aggrid.py +0 -0
  63. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_date_picker.js +0 -0
  64. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_date_picker.py +0 -0
  65. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_echarts.py +0 -0
  66. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_radio.py +0 -0
  67. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_range.py +0 -0
  68. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_select.py +0 -0
  69. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_slider.py +0 -0
  70. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/elements/ui_table.py +0 -0
  71. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/protocols.py +0 -0
  72. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/bi/types.py +0 -0
  73. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/experimental_/__init__.py +0 -0
  74. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/experimental_/gridLayout/__init__.py +0 -0
  75. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/experimental_/gridLayout/index.py +0 -0
  76. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/gsap/__init__.py +0 -0
  77. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/gsap/gsap.py +0 -0
  78. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/gsap/timeline.js +0 -0
  79. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/gsap/timeline.py +0 -0
  80. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/gsap/wrapGsap.js +0 -0
  81. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/helper/__init__.py +0 -0
  82. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/helper/client_instance_locker.py +0 -0
  83. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/__init__.py +0 -0
  84. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/gridFlex/GridFlex.js +0 -0
  85. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/gridFlex/__init__.py +0 -0
  86. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/gridFlex/gridFlex.py +0 -0
  87. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/gridFlex/utils.py +0 -0
  88. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/rxFlex/__init__.py +0 -0
  89. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/rxFlex/index.py +0 -0
  90. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/layout/rxFlex/types.py +0 -0
  91. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/__init__.py +0 -0
  92. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/__init__.py +0 -0
  93. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-color.ems.js +0 -0
  94. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-dispatch.ems.js +0 -0
  95. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-drag.ems.js +0 -0
  96. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-ease.ems.js +0 -0
  97. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-interpolate.ems.js +0 -0
  98. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-selection.ems.js +0 -0
  99. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-timer.ems.js +0 -0
  100. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-transition.ems.js +0 -0
  101. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/d3/d3-zoom.ems.js +0 -0
  102. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/.DS_Store +0 -0
  103. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/CSSPlugin.js +0 -0
  104. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/CSSRulePlugin.js +0 -0
  105. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/CustomEase.js +0 -0
  106. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/Draggable.js +0 -0
  107. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/EasePack.js +0 -0
  108. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/EaselPlugin.js +0 -0
  109. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/Flip.js +0 -0
  110. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/MotionPathPlugin.js +0 -0
  111. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/Observer.js +0 -0
  112. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/PixiPlugin.js +0 -0
  113. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/ScrollToPlugin.js +0 -0
  114. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/ScrollTrigger.js +0 -0
  115. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/TextPlugin.js +0 -0
  116. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/__init__.py +0 -0
  117. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/all.js +0 -0
  118. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/gsap-core.js +0 -0
  119. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/gsap.mjs +0 -0
  120. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/utils/__init__.py +0 -0
  121. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/utils/matrix.js +0 -0
  122. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/utils/paths.js +0 -0
  123. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/libs/gsap/utils/strings.js +0 -0
  124. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/EChartsComponent/ECharts.js +0 -0
  125. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/EChartsComponent/events.py +0 -0
  126. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/EChartsComponent/types.py +0 -0
  127. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/EChartsComponent/utils.py +0 -0
  128. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/UseDraggable/UseDraggable.js +0 -0
  129. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/UseDraggable/UseDraggable.py +0 -0
  130. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/deferredTask.py +0 -0
  131. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/dropZone/dropZone.js +0 -0
  132. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/dropZone/dropZone.py +0 -0
  133. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/empty.js +0 -0
  134. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/empty.py +0 -0
  135. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/fileWatcher.py +0 -0
  136. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/local_file_picker.py +0 -0
  137. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/mermaid/mermaid.js +0 -0
  138. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/mermaid/mermaid.py +0 -0
  139. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/base.py +0 -0
  140. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/card.py +0 -0
  141. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/drawer.py +0 -0
  142. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/element.py +0 -0
  143. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/grid.py +0 -0
  144. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/html.js +0 -0
  145. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/html.py +0 -0
  146. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/tab_panel.py +0 -0
  147. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/officials/upload.py +0 -0
  148. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/rxui.py +0 -0
  149. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/scopedStyle.js +0 -0
  150. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/scopedStyle.py +0 -0
  151. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/services/pandas_service.py +0 -0
  152. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/services/reactive_service.py +0 -0
  153. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/systems/color_system.py +0 -0
  154. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/systems/object_system.py +0 -0
  155. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/transitionGroup.js +0 -0
  156. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/transitionGroup.py +0 -0
  157. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/useMouse/UseMouse.js +0 -0
  158. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/useMouse/UseMouse.py +0 -0
  159. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/reactive/usePagination.py +0 -0
  160. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/tools/__init__.py +0 -0
  161. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/tools/debug.py +0 -0
  162. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/__init__.py +0 -0
  163. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/apiEffect.py +0 -0
  164. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/asyncComputed.py +0 -0
  165. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/clientScope.py +0 -0
  166. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/common.py +0 -0
  167. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/effect.py +0 -0
  168. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/refComputed.py +0 -0
  169. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/refWrapper.py +0 -0
  170. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/scheduler.py +0 -0
  171. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/utils/types.py +0 -0
  172. {ex4nicegui-0.6.9 → ex4nicegui-0.7.1}/ex4nicegui/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ex4nicegui
3
- Version: 0.6.9
3
+ Version: 0.7.1
4
4
  Summary: Extension library based on nicegui, providing data responsive,BI functionality modules
5
5
  Home-page: https://github.com/CrystalWindSnake/ex4nicegui
6
6
  License: MIT
@@ -17,13 +17,17 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Requires-Dist: executing (>=2.0.1,<3.0.0)
19
19
  Requires-Dist: nicegui (>=1.4.25,<2.0.0)
20
- Requires-Dist: signe (>=0.4.14,<0.5.0)
20
+ Requires-Dist: signe (>=0.4.20,<0.5.0)
21
21
  Project-URL: Repository, https://github.com/CrystalWindSnake/ex4nicegui
22
22
  Description-Content-Type: text/markdown
23
23
 
24
24
  # ex4nicegui
25
- [ENGLISH README](./README.en.md)
26
25
 
26
+ <div align="center">
27
+
28
+ 简体中文| [English](./README.en.md)
29
+
30
+ </div>
27
31
 
28
32
  - [教程](#教程)
29
33
  - [安装](#-安装)
@@ -34,6 +38,10 @@ Description-Content-Type: text/markdown
34
38
  对 [nicegui](https://github.com/zauberzeug/nicegui) 做的扩展库。内置响应式组件,完全实现数据响应式界面编程。
35
39
 
36
40
 
41
+ ![todo-app](https://github.com/CrystalWindSnake/ex4nicegui-examples/blob/main/asset/todo-app.02.gif)
42
+
43
+ [查看更多示例](https://github.com/CrystalWindSnake/ex4nicegui-examples)
44
+
37
45
  ## 教程
38
46
  [头条文章-秒杀官方实现,python界面库,去掉90%事件代码的nicegui](https://www.toutiao.com/item/7253786340574265860/)
39
47
 
@@ -191,6 +199,154 @@ ui.run()
191
199
  ---
192
200
 
193
201
 
202
+
203
+ ## ViewModel
204
+ 在 `v0.7.0` 版本中,引入 `ViewModel` 类,用于管理一组响应式数据。
205
+
206
+ 下面是一个简单的计算器示例:
207
+
208
+ 1. 当用户修改数值输入框或符号选择框,右侧会自动显示计算结果
209
+ 2. 当结果小于 0 时,结果显示为红色,否则为黑色
210
+
211
+ ```python
212
+ from ex4nicegui import rxui
213
+
214
+ class Calculator(rxui.ViewModel):
215
+ num1 = rxui.var(0)
216
+ sign = rxui.var("+")
217
+ num2 = rxui.var(0)
218
+
219
+ def result(self):
220
+ # 当 num1,sign,num2 任意一个值发生变化时,result 也会重新计算
221
+ return eval(f"{self.num1.value}{self.sign.value}{self.num2.value}")
222
+
223
+ # 每个对象拥有独立的数据
224
+ calc = Calculator()
225
+
226
+ with ui.row(align_items="center"):
227
+ rxui.number(value=calc.num1, label="Number 1")
228
+ rxui.select(value=calc.sign, options=["+", "-", "*", "/"], label="Sign")
229
+ rxui.number(value=calc.num2, label="Number 2")
230
+ ui.label("=")
231
+ rxui.label(calc.result).bind_color(
232
+ lambda: "red" if calc.result() < 0 else "black"
233
+ )
234
+
235
+ ```
236
+
237
+ ### cached_var
238
+
239
+ 上面的示例中,由于使用了两次 `calc.result` 。因此,每当 `num1`, `sign`, `num2` 任意一个值发生变化时,`result` 都会执行2次。
240
+
241
+ 实际上,第二次的计算是多余的。我们可以通过添加 `rxui.cached_var` 装饰器,避免多余的计算。
242
+
243
+ ```python
244
+ class Calculator(rxui.ViewModel):
245
+ ...
246
+
247
+ @rxui.cached_var
248
+ def result(self):
249
+ return eval(f"{self.num1.value}{self.sign.value}{self.num2.value}")
250
+
251
+ ...
252
+ ```
253
+
254
+ ---
255
+
256
+ ### 使用列表
257
+
258
+ 当数据为可变对象时,比如列表,字典等,需要提供工厂函数传给 `rxui.var`
259
+
260
+
261
+ ```python
262
+ class Home(rxui.ViewModel):
263
+ persons= rxui.var(lambda: [])
264
+
265
+ ```
266
+
267
+ 下面的示例,每个 person 使用卡片展示。最上方显示所有人的平均年龄。当个人年龄大于平均年龄,卡片外边框将变为红色。
268
+ 通过 `number` 组件修改年龄,一切都会自动更新。
269
+
270
+ ```python
271
+ from ex4nicegui import rxui, Ref
272
+ from itertools import count
273
+
274
+ id_generator = count()
275
+
276
+ class Person(rxui.ViewModel):
277
+ name = rxui.var("")
278
+ age = rxui.var(0)
279
+
280
+ def __init__(self, name: str = "", age: int = 0):
281
+ super().__init__()
282
+ self.name.value = name
283
+ self.age.value = age
284
+ self.id = next(id_generator)
285
+
286
+
287
+ class Home(rxui.ViewModel):
288
+ persons: Ref[List[Person]] = rxui.var(lambda: [])
289
+
290
+ def avg_age(self) -> float:
291
+ if len(self.persons.value) == 0:
292
+ return 0
293
+
294
+ return sum(p.age.value for p in self.persons.value) / len(self.persons.value)
295
+
296
+ def sample_data(self):
297
+ self.persons.value = [
298
+ Person("alice", 25),
299
+ Person("bob", 30),
300
+ Person("charlie", 31),
301
+ Person("dave", 22),
302
+ Person("eve", 26),
303
+ Person("frank", 29),
304
+ ]
305
+
306
+ home = Home()
307
+ home.sample_data()
308
+
309
+ rxui.label(lambda: f"平均年龄: {home.avg_age()}")
310
+
311
+
312
+ with ui.row():
313
+
314
+ @rxui.vfor(home.persons, key="id")
315
+ def _(store: rxui.VforStore[Person]):
316
+ person = store.get_item()
317
+ with rxui.card().classes("outline").bind_classes(
318
+ {
319
+ "outline-red-500": lambda: person.age.value > home.avg_age(),
320
+ }
321
+ ):
322
+ rxui.input(value=person.name, placeholder="名字")
323
+ rxui.number(value=person.age, min=1, max=100, step=1, placeholder="年龄")
324
+
325
+ ```
326
+
327
+ 如果你觉得 `rxui.vfor` 代码过于复杂,可以使用 `effect_refreshable` 装饰器代替。
328
+
329
+ ```python
330
+ from ex4nicegui import rxui, Ref,effect_refreshable
331
+ ...
332
+
333
+ # 明确指定监控 home.persons 变化,可以避免意味刷新
334
+ @effect_refreshable.on(home.persons)
335
+ def _():
336
+
337
+ for person in home.persons.value:
338
+ ...
339
+ rxui.number(value=person.age, min=1, max=100, step=1, placeholder="年龄")
340
+ ...
341
+ ```
342
+
343
+ 需要注意到,每当 `home.persons` 列表变化时(比如新增或删除元素),`effect_refreshable` 装饰的函数都会重新执行。意味着所有元素都会重新创建。
344
+
345
+
346
+ 更多复杂的应用,可以查看 [examples](./examples)
347
+
348
+ ---
349
+
194
350
  ## 响应式
195
351
 
196
352
  ```python
@@ -331,15 +487,14 @@ ui.button("change", on_click=change_value)
331
487
 
332
488
  > `ref_computed` 是只读的 `to_ref`
333
489
 
334
-
335
- 如果你更喜欢通过类组织代码,`ref_computed` 同样支持作用到实例方法上
490
+ 从 `v0.7.0` 版本开始,不建议使用 `ref_computed` 应用实例方法。你可以使用 `rxui.ViewModel`,并使用 `rxui.cached_var` 装饰器
336
491
 
337
492
  ```python
338
- class MyState:
493
+ class MyState(rxui.ViewModel):
339
494
  def __init__(self) -> None:
340
495
  self.r_text = to_ref("")
341
496
 
342
- @ref_computed
497
+ @rxui.cached_var
343
498
  def post_text(self):
344
499
  return self.r_text.value + "post"
345
500
 
@@ -494,70 +649,90 @@ rxui.input(value=data.value["a"])
494
649
  rxui.input(value=lambda: data.value["a"])
495
650
 
496
651
  # 要使用 vmodel 才能双向绑定
497
- rxui.input(value=rxui.vmodel(data.value["a"]))
652
+ rxui.input(value=rxui.vmodel(data, "a"))
653
+
654
+ # 也可以直接使用,但不推荐
655
+ rxui.input(value=rxui.vmodel(data.value['a']))
656
+
498
657
  ```
499
658
 
500
- - 第一个输入框将完全失去响应性,因为代码等价于直接传入一个数值`1`
659
+ - 第一个输入框将完全失去响应性,因为代码等价于 `rxui.input(value=1)`
501
660
  - 第二个输入框由于使用函数,将得到读取响应性(第三个输入框输入值,将得到同步)
502
661
  - 第三个输入框,使用 `rxui.vmodel` 包裹,即可实现双向绑定
503
662
 
504
- 多数在配合 `vfor` 时使用 `vmodel`,可参考 [todo list 案例](./examples/todomvc/)
663
+ > 如果使用 `rxui.ViewModel` ,你可能不需要使用 `vmodel`
505
664
 
665
+ 可参考 [todo list 案例](./examples/todomvc/)
666
+
667
+ ---
506
668
 
507
669
  ### vfor
508
- 基于列表响应式数据,渲染列表组件。每项组件按需更新。数据项支持字典或任意类型对象
670
+ 基于列表响应式数据,渲染列表组件。每项组件按需更新。数据项支持字典或任意类型对象。
671
+
672
+ 从 `v0.7.0` 版本开始,建议配合 `rxui.ViewModel` 使用。与使用 `effect_refreshable` 装饰器不同,`vfor` 不会重新创建所有的元素,而是更新已存在的元素。
673
+
674
+ 下面是卡片排序例子,卡片总是按年龄排序。当你修改某个卡片中的年龄数据时,卡片会实时调整顺序。但是,光标焦点不会离开输入框。
675
+
509
676
 
510
677
  ```python
678
+ from typing import List
511
679
  from nicegui import ui
512
- from ex4nicegui.reactive import rxui
513
- from ex4nicegui import deep_ref, ref_computed
514
- from typing import Dict
515
-
516
- # refs
517
- items = deep_ref(
518
- [
519
- {"id": 1, "message": "foo", "done": False},
520
- {"id": 2, "message": "bar", "done": True},
521
- ]
522
- )
680
+ from ex4nicegui import rxui, deep_ref as ref, Ref
523
681
 
524
- # ref_computeds
525
- @ref_computed
526
- def done_count_info():
527
- return f"done count:{sum(item['done'] for item in items.value)}"
528
682
 
529
- # method
530
- def check():
531
- for item in items.value:
532
- item["done"] = not item["done"]
683
+ class Person(rxui.ViewModel):
684
+ def __init__(self, name: str, age: int) -> None:
685
+ self.name = name
686
+ self.age = ref(age)
687
+
688
+
689
+ class MyApp(rxui.ViewModel):
690
+ persons: Ref[List[Person]] = rxui.var(lambda: [])
691
+ order = rxui.var("asc")
692
+
693
+ def sort_by_age(self):
694
+ return sorted(
695
+ self.persons.value,
696
+ key=lambda p: p.age.value,
697
+ reverse=self.order.value == "desc",
698
+ )
699
+
700
+ @staticmethod
701
+ def create():
702
+ persons = [
703
+ Person(name="Alice", age=25),
704
+ Person(name="Bob", age=30),
705
+ Person(name="Charlie", age=20),
706
+ Person(name="Dave", age=35),
707
+ Person(name="Eve", age=28),
708
+ ]
709
+ app = MyApp()
710
+ app.persons.value = persons
711
+ return app
533
712
 
534
713
 
535
714
  # ui
536
- rxui.label(done_count_info)
537
- ui.button("check", on_click=check)
715
+ app = MyApp.create()
538
716
 
717
+ with rxui.tabs(app.order):
718
+ rxui.tab("asc", "Ascending")
719
+ rxui.tab("desc", "Descending")
539
720
 
540
- @rxui.vfor(items,key='id')
541
- def _(store: rxui.VforStore[Dict]):
542
- # 函数中构建每一行数据的界面
543
- item = store.get() # 通过 store.get 获取对应行的响应式对象(相当于每行的数据 to_ref(...))
544
- mes = rxui.vmodel(item.value['message']) # 复杂结构默认没有双向绑定,需要使用 `vmodel`
545
721
 
546
- # 输入框输入内容,可以看到单选框的标题同步变化
547
- with ui.card():
548
- with ui.row():
549
- rxui.input(value=mes)
550
- rxui.label(lambda: f"{mes.value=!s}")
551
- rxui.checkbox(text=mes, value=rxui.vmodel(item.value['done']))
722
+ @rxui.vfor(app.sort_by_age, key="name")
723
+ def each_person(s: rxui.VforStore[Person]):
724
+ person = s.get_item()
725
+
726
+ with ui.card(), ui.row(align_items="center"):
727
+ rxui.label(person.name)
728
+ rxui.number(value=person.age, step=1, min=0, max=100)
552
729
 
553
730
  ```
554
731
 
555
732
  - `rxui.vfor` 装饰器到自定义函数
556
- - 第一个参数传入响应式列表。列表中每一项可以是字典或其他对象(`dataclasses` 等等)
557
- - 第二个参数 `key`: 为了可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你可以为每个元素对应的块提供一个唯一的 key 。默认情况使用列表元素索引。
558
- - 自定义函数带有一个参数。通过 `store.get` 可以获取当前行的响应式对象
559
-
560
- > vfor 渲染的项目,只有在新增数据时,才会创建
733
+ - 第一个参数传入响应式列表。注意,无须调用 `app.sort_by_age`
734
+ - 第二个参数 `key`: 为了可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你可以为每个元素对应的块提供一个唯一的 key 。默认情况使用列表元素索引。例子中假定每个人的名字唯一。
735
+ - 自定义函数带有一个参数。通过 `store.get_item` 可以获取当前行的对象。由于 Person 本身继承自 `rxui.ViewModel`,所以它的各项属性可以直接绑定到组件。
561
736
 
562
737
 
563
738
  ---
@@ -1,6 +1,10 @@
1
1
  # ex4nicegui
2
- [ENGLISH README](./README.en.md)
3
2
 
3
+ <div align="center">
4
+
5
+ 简体中文| [English](./README.en.md)
6
+
7
+ </div>
4
8
 
5
9
  - [教程](#教程)
6
10
  - [安装](#-安装)
@@ -11,6 +15,10 @@
11
15
  对 [nicegui](https://github.com/zauberzeug/nicegui) 做的扩展库。内置响应式组件,完全实现数据响应式界面编程。
12
16
 
13
17
 
18
+ ![todo-app](https://github.com/CrystalWindSnake/ex4nicegui-examples/blob/main/asset/todo-app.02.gif)
19
+
20
+ [查看更多示例](https://github.com/CrystalWindSnake/ex4nicegui-examples)
21
+
14
22
  ## 教程
15
23
  [头条文章-秒杀官方实现,python界面库,去掉90%事件代码的nicegui](https://www.toutiao.com/item/7253786340574265860/)
16
24
 
@@ -168,6 +176,154 @@ ui.run()
168
176
  ---
169
177
 
170
178
 
179
+
180
+ ## ViewModel
181
+ 在 `v0.7.0` 版本中,引入 `ViewModel` 类,用于管理一组响应式数据。
182
+
183
+ 下面是一个简单的计算器示例:
184
+
185
+ 1. 当用户修改数值输入框或符号选择框,右侧会自动显示计算结果
186
+ 2. 当结果小于 0 时,结果显示为红色,否则为黑色
187
+
188
+ ```python
189
+ from ex4nicegui import rxui
190
+
191
+ class Calculator(rxui.ViewModel):
192
+ num1 = rxui.var(0)
193
+ sign = rxui.var("+")
194
+ num2 = rxui.var(0)
195
+
196
+ def result(self):
197
+ # 当 num1,sign,num2 任意一个值发生变化时,result 也会重新计算
198
+ return eval(f"{self.num1.value}{self.sign.value}{self.num2.value}")
199
+
200
+ # 每个对象拥有独立的数据
201
+ calc = Calculator()
202
+
203
+ with ui.row(align_items="center"):
204
+ rxui.number(value=calc.num1, label="Number 1")
205
+ rxui.select(value=calc.sign, options=["+", "-", "*", "/"], label="Sign")
206
+ rxui.number(value=calc.num2, label="Number 2")
207
+ ui.label("=")
208
+ rxui.label(calc.result).bind_color(
209
+ lambda: "red" if calc.result() < 0 else "black"
210
+ )
211
+
212
+ ```
213
+
214
+ ### cached_var
215
+
216
+ 上面的示例中,由于使用了两次 `calc.result` 。因此,每当 `num1`, `sign`, `num2` 任意一个值发生变化时,`result` 都会执行2次。
217
+
218
+ 实际上,第二次的计算是多余的。我们可以通过添加 `rxui.cached_var` 装饰器,避免多余的计算。
219
+
220
+ ```python
221
+ class Calculator(rxui.ViewModel):
222
+ ...
223
+
224
+ @rxui.cached_var
225
+ def result(self):
226
+ return eval(f"{self.num1.value}{self.sign.value}{self.num2.value}")
227
+
228
+ ...
229
+ ```
230
+
231
+ ---
232
+
233
+ ### 使用列表
234
+
235
+ 当数据为可变对象时,比如列表,字典等,需要提供工厂函数传给 `rxui.var`
236
+
237
+
238
+ ```python
239
+ class Home(rxui.ViewModel):
240
+ persons= rxui.var(lambda: [])
241
+
242
+ ```
243
+
244
+ 下面的示例,每个 person 使用卡片展示。最上方显示所有人的平均年龄。当个人年龄大于平均年龄,卡片外边框将变为红色。
245
+ 通过 `number` 组件修改年龄,一切都会自动更新。
246
+
247
+ ```python
248
+ from ex4nicegui import rxui, Ref
249
+ from itertools import count
250
+
251
+ id_generator = count()
252
+
253
+ class Person(rxui.ViewModel):
254
+ name = rxui.var("")
255
+ age = rxui.var(0)
256
+
257
+ def __init__(self, name: str = "", age: int = 0):
258
+ super().__init__()
259
+ self.name.value = name
260
+ self.age.value = age
261
+ self.id = next(id_generator)
262
+
263
+
264
+ class Home(rxui.ViewModel):
265
+ persons: Ref[List[Person]] = rxui.var(lambda: [])
266
+
267
+ def avg_age(self) -> float:
268
+ if len(self.persons.value) == 0:
269
+ return 0
270
+
271
+ return sum(p.age.value for p in self.persons.value) / len(self.persons.value)
272
+
273
+ def sample_data(self):
274
+ self.persons.value = [
275
+ Person("alice", 25),
276
+ Person("bob", 30),
277
+ Person("charlie", 31),
278
+ Person("dave", 22),
279
+ Person("eve", 26),
280
+ Person("frank", 29),
281
+ ]
282
+
283
+ home = Home()
284
+ home.sample_data()
285
+
286
+ rxui.label(lambda: f"平均年龄: {home.avg_age()}")
287
+
288
+
289
+ with ui.row():
290
+
291
+ @rxui.vfor(home.persons, key="id")
292
+ def _(store: rxui.VforStore[Person]):
293
+ person = store.get_item()
294
+ with rxui.card().classes("outline").bind_classes(
295
+ {
296
+ "outline-red-500": lambda: person.age.value > home.avg_age(),
297
+ }
298
+ ):
299
+ rxui.input(value=person.name, placeholder="名字")
300
+ rxui.number(value=person.age, min=1, max=100, step=1, placeholder="年龄")
301
+
302
+ ```
303
+
304
+ 如果你觉得 `rxui.vfor` 代码过于复杂,可以使用 `effect_refreshable` 装饰器代替。
305
+
306
+ ```python
307
+ from ex4nicegui import rxui, Ref,effect_refreshable
308
+ ...
309
+
310
+ # 明确指定监控 home.persons 变化,可以避免意味刷新
311
+ @effect_refreshable.on(home.persons)
312
+ def _():
313
+
314
+ for person in home.persons.value:
315
+ ...
316
+ rxui.number(value=person.age, min=1, max=100, step=1, placeholder="年龄")
317
+ ...
318
+ ```
319
+
320
+ 需要注意到,每当 `home.persons` 列表变化时(比如新增或删除元素),`effect_refreshable` 装饰的函数都会重新执行。意味着所有元素都会重新创建。
321
+
322
+
323
+ 更多复杂的应用,可以查看 [examples](./examples)
324
+
325
+ ---
326
+
171
327
  ## 响应式
172
328
 
173
329
  ```python
@@ -308,15 +464,14 @@ ui.button("change", on_click=change_value)
308
464
 
309
465
  > `ref_computed` 是只读的 `to_ref`
310
466
 
311
-
312
- 如果你更喜欢通过类组织代码,`ref_computed` 同样支持作用到实例方法上
467
+ 从 `v0.7.0` 版本开始,不建议使用 `ref_computed` 应用实例方法。你可以使用 `rxui.ViewModel`,并使用 `rxui.cached_var` 装饰器
313
468
 
314
469
  ```python
315
- class MyState:
470
+ class MyState(rxui.ViewModel):
316
471
  def __init__(self) -> None:
317
472
  self.r_text = to_ref("")
318
473
 
319
- @ref_computed
474
+ @rxui.cached_var
320
475
  def post_text(self):
321
476
  return self.r_text.value + "post"
322
477
 
@@ -471,70 +626,90 @@ rxui.input(value=data.value["a"])
471
626
  rxui.input(value=lambda: data.value["a"])
472
627
 
473
628
  # 要使用 vmodel 才能双向绑定
474
- rxui.input(value=rxui.vmodel(data.value["a"]))
629
+ rxui.input(value=rxui.vmodel(data, "a"))
630
+
631
+ # 也可以直接使用,但不推荐
632
+ rxui.input(value=rxui.vmodel(data.value['a']))
633
+
475
634
  ```
476
635
 
477
- - 第一个输入框将完全失去响应性,因为代码等价于直接传入一个数值`1`
636
+ - 第一个输入框将完全失去响应性,因为代码等价于 `rxui.input(value=1)`
478
637
  - 第二个输入框由于使用函数,将得到读取响应性(第三个输入框输入值,将得到同步)
479
638
  - 第三个输入框,使用 `rxui.vmodel` 包裹,即可实现双向绑定
480
639
 
481
- 多数在配合 `vfor` 时使用 `vmodel`,可参考 [todo list 案例](./examples/todomvc/)
640
+ > 如果使用 `rxui.ViewModel` ,你可能不需要使用 `vmodel`
482
641
 
642
+ 可参考 [todo list 案例](./examples/todomvc/)
643
+
644
+ ---
483
645
 
484
646
  ### vfor
485
- 基于列表响应式数据,渲染列表组件。每项组件按需更新。数据项支持字典或任意类型对象
647
+ 基于列表响应式数据,渲染列表组件。每项组件按需更新。数据项支持字典或任意类型对象。
648
+
649
+ 从 `v0.7.0` 版本开始,建议配合 `rxui.ViewModel` 使用。与使用 `effect_refreshable` 装饰器不同,`vfor` 不会重新创建所有的元素,而是更新已存在的元素。
650
+
651
+ 下面是卡片排序例子,卡片总是按年龄排序。当你修改某个卡片中的年龄数据时,卡片会实时调整顺序。但是,光标焦点不会离开输入框。
652
+
486
653
 
487
654
  ```python
655
+ from typing import List
488
656
  from nicegui import ui
489
- from ex4nicegui.reactive import rxui
490
- from ex4nicegui import deep_ref, ref_computed
491
- from typing import Dict
492
-
493
- # refs
494
- items = deep_ref(
495
- [
496
- {"id": 1, "message": "foo", "done": False},
497
- {"id": 2, "message": "bar", "done": True},
498
- ]
499
- )
657
+ from ex4nicegui import rxui, deep_ref as ref, Ref
500
658
 
501
- # ref_computeds
502
- @ref_computed
503
- def done_count_info():
504
- return f"done count:{sum(item['done'] for item in items.value)}"
505
659
 
506
- # method
507
- def check():
508
- for item in items.value:
509
- item["done"] = not item["done"]
660
+ class Person(rxui.ViewModel):
661
+ def __init__(self, name: str, age: int) -> None:
662
+ self.name = name
663
+ self.age = ref(age)
664
+
665
+
666
+ class MyApp(rxui.ViewModel):
667
+ persons: Ref[List[Person]] = rxui.var(lambda: [])
668
+ order = rxui.var("asc")
669
+
670
+ def sort_by_age(self):
671
+ return sorted(
672
+ self.persons.value,
673
+ key=lambda p: p.age.value,
674
+ reverse=self.order.value == "desc",
675
+ )
676
+
677
+ @staticmethod
678
+ def create():
679
+ persons = [
680
+ Person(name="Alice", age=25),
681
+ Person(name="Bob", age=30),
682
+ Person(name="Charlie", age=20),
683
+ Person(name="Dave", age=35),
684
+ Person(name="Eve", age=28),
685
+ ]
686
+ app = MyApp()
687
+ app.persons.value = persons
688
+ return app
510
689
 
511
690
 
512
691
  # ui
513
- rxui.label(done_count_info)
514
- ui.button("check", on_click=check)
692
+ app = MyApp.create()
515
693
 
694
+ with rxui.tabs(app.order):
695
+ rxui.tab("asc", "Ascending")
696
+ rxui.tab("desc", "Descending")
516
697
 
517
- @rxui.vfor(items,key='id')
518
- def _(store: rxui.VforStore[Dict]):
519
- # 函数中构建每一行数据的界面
520
- item = store.get() # 通过 store.get 获取对应行的响应式对象(相当于每行的数据 to_ref(...))
521
- mes = rxui.vmodel(item.value['message']) # 复杂结构默认没有双向绑定,需要使用 `vmodel`
522
698
 
523
- # 输入框输入内容,可以看到单选框的标题同步变化
524
- with ui.card():
525
- with ui.row():
526
- rxui.input(value=mes)
527
- rxui.label(lambda: f"{mes.value=!s}")
528
- rxui.checkbox(text=mes, value=rxui.vmodel(item.value['done']))
699
+ @rxui.vfor(app.sort_by_age, key="name")
700
+ def each_person(s: rxui.VforStore[Person]):
701
+ person = s.get_item()
702
+
703
+ with ui.card(), ui.row(align_items="center"):
704
+ rxui.label(person.name)
705
+ rxui.number(value=person.age, step=1, min=0, max=100)
529
706
 
530
707
  ```
531
708
 
532
709
  - `rxui.vfor` 装饰器到自定义函数
533
- - 第一个参数传入响应式列表。列表中每一项可以是字典或其他对象(`dataclasses` 等等)
534
- - 第二个参数 `key`: 为了可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你可以为每个元素对应的块提供一个唯一的 key 。默认情况使用列表元素索引。
535
- - 自定义函数带有一个参数。通过 `store.get` 可以获取当前行的响应式对象
536
-
537
- > vfor 渲染的项目,只有在新增数据时,才会创建
710
+ - 第一个参数传入响应式列表。注意,无须调用 `app.sort_by_age`
711
+ - 第二个参数 `key`: 为了可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你可以为每个元素对应的块提供一个唯一的 key 。默认情况使用列表元素索引。例子中假定每个人的名字唯一。
712
+ - 自定义函数带有一个参数。通过 `store.get_item` 可以获取当前行的对象。由于 Person 本身继承自 `rxui.ViewModel`,所以它的各项属性可以直接绑定到组件。
538
713
 
539
714
 
540
715
  ---