浏览代码

update client-handshake example

Falko Schindler 2 年之前
父节点
当前提交
90c1e8740c
共有 5 个文件被更改,包括 26 次插入20 次删除
  1. 14 18
      api_docs_and_examples.py
  2. 1 0
      nicegui/__init__.py
  3. 4 0
      nicegui/client.py
  4. 2 2
      nicegui/element.py
  5. 5 0
      nicegui/slot.py

+ 14 - 18
api_docs_and_examples.py

@@ -701,33 +701,29 @@ If the page function expects a `request` argument, the request object is automat
 
 
         ui.link('Say hi to Santa!', 'repeat/Ho! /3')
         ui.link('Say hi to Santa!', 'repeat/Ho! /3')
 
 
-    @example('''#### Yielding for Page-Ready
+    @example('''#### Wait for Handshake with Client
 
 
-This is a handy alternative to the `on_page_ready` callback of the `@ui.page` decorator.
+To wait for a client connection, you can add a `client` argument to the decorated page function
+and await `client.handshake()`.
+All code below that statement is executed after the websocket connection between server and client has been established.
 
 
-If a `yield` statement is provided in a page builder function, all code below that statement is executed after the page is ready.
-This allows you to execute JavaScript; which is only possible after the page has been loaded (see [#112](https://github.com/zauberzeug/nicegui/issues/112)).
-Also it is possible to do async stuff while the user already sees the content which was added before the yield statement.
-
-The yield statement returns `nicegui.events.PageEvent`. 
-This contains the websocket of the client.
-    ''')
-    def yield_page_ready_example():
+For example, this allows you to run JavaScript commands; which is only possible with a client connection (see [#112](https://github.com/zauberzeug/nicegui/issues/112)).
+Also it is possible to do async stuff while the user already sees some content.
+    ''', skip=False)
+    def wait_for_handshake_example():
         import asyncio
         import asyncio
-        from typing import Generator
 
 
-        from nicegui.events import PageEvent
+        from nicegui import Client
 
 
-        @ui.page('/yield_page_ready')
-        async def yield_page_ready() -> Generator[None, PageEvent, None]:
+        @ui.page('/wait_for_handshake')
+        async def wait_for_handshake(client: Client):
             ui.label('This text is displayed immediately.')
             ui.label('This text is displayed immediately.')
-            page_ready = yield
-            await ui.run_javascript('document.title = "JavaScript-Controlled Title")')
+            await client.handshake()
             await asyncio.sleep(2)
             await asyncio.sleep(2)
             ui.label('This text is displayed 2 seconds after the page has been fully loaded.')
             ui.label('This text is displayed 2 seconds after the page has been fully loaded.')
-            ui.label(f'The IP address {page_ready.socket.client.host} could be obtained from the websocket.')
+            ui.label(f'The IP address {client.ip} was obtained from the websocket.')
 
 
-        ui.link('show page-ready code after yield', '/yield_page_ready')
+        ui.link('wait for handshake', wait_for_handshake)
 
 
     @example('''#### Page Layout
     @example('''#### Page Layout
 
 

+ 1 - 0
nicegui/__init__.py

@@ -1,2 +1,3 @@
 from . import elements, globals, ui
 from . import elements, globals, ui
+from .client import Client
 from .nicegui import app
 from .nicegui import app

+ 4 - 0
nicegui/client.py

@@ -30,6 +30,10 @@ class Client:
         self.content = ui.column().classes('q-ma-md')
         self.content = ui.column().classes('q-ma-md')
         globals.client_stack.pop()
         globals.client_stack.pop()
 
 
+    @property
+    def ip(self) -> Optional[str]:
+        return self.environ.get('REMOTE_ADDR') if self.environ else None
+
     def __enter__(self):
     def __enter__(self):
         globals.client_stack.append(self)
         globals.client_stack.append(self)
         self.content.__enter__()
         self.content.__enter__()

+ 2 - 2
nicegui/element.py

@@ -34,11 +34,11 @@ class Element(ABC, Visibility):
         return self.slots[name]
         return self.slots[name]
 
 
     def __enter__(self):
     def __enter__(self):
-        self.client.slot_stack.append(self.default_slot)
+        self.default_slot.__enter__()
         return self
         return self
 
 
     def __exit__(self, *_):
     def __exit__(self, *_):
-        self.client.slot_stack.pop()
+        self.default_slot.__exit__(*_)
 
 
     def to_dict(self) -> Dict:
     def to_dict(self) -> Dict:
         events: Dict[str, List[str]] = {}
         events: Dict[str, List[str]] = {}

+ 5 - 0
nicegui/slot.py

@@ -13,9 +13,14 @@ class Slot:
         self.parent = parent
         self.parent = parent
         self.children: List['Element'] = []
         self.children: List['Element'] = []
 
 
+        self._child_count_before_enter = 0
+
     def __enter__(self):
     def __enter__(self):
+        self._child_count_before_enter = len(self.children)
         globals.client_stack[-1].slot_stack.append(self)
         globals.client_stack[-1].slot_stack.append(self)
         return self
         return self
 
 
     def __exit__(self, *_):
     def __exit__(self, *_):
         globals.client_stack[-1].slot_stack.pop()
         globals.client_stack[-1].slot_stack.pop()
+        if len(self.children) != self._child_count_before_enter:
+            self.parent.update()