2
2
Widget Tools
3
3
============
4
4
"""
5
+ from __future__ import annotations
5
6
6
- from typing import Any , Callable , Dict , Set , Tuple , TypeVar
7
+ from typing import Any , Callable , Dict , Optional , Set , Tuple , TypeVar
7
8
8
9
from idom .core import hooks
9
10
from idom .core .component import ComponentConstructor , component
@@ -97,30 +98,36 @@ def _use_callable(initial_func: _FuncVar) -> Tuple[_FuncVar, Callable[[_Func], N
97
98
return state [0 ], lambda new : state [1 ](lambda old : new )
98
99
99
100
100
- def multiview () -> Tuple [" MultiViewMount" , ComponentConstructor ]:
101
+ def multiview () -> Tuple [MultiViewMount , ComponentConstructor ]:
101
102
"""Dynamically add components to a layout on the fly
102
103
103
104
Since you can't change the component functions used to create a layout
104
105
in an imperative manner, you can use ``multiview`` to do this so
105
106
long as you set things up ahead of time.
106
107
107
- Returns:
108
- A function for adding views and the root of the dynamic view
109
-
110
108
Examples:
111
109
112
110
.. code-block::
113
111
114
112
import idom
115
113
116
- define, root = idom.widgets.multiview()
114
+ mount, multiview = idom.widgets.multiview()
115
+
116
+ @idom.component
117
+ def Hello():
118
+ return idom.html.h1(["hello"])
117
119
118
- @component
119
- def Hello(self, phrase):
120
- return idom.html.h1(["hello " + phrase])
120
+ # auto static view ID
121
+ mount.add("hello", Hello)
122
+ # use the view ID to create the associate component instance
123
+ hello_component_instance = multiview("hello")
121
124
122
- add_hello = define(Hello)
123
- hello_world_view_id = add_hello("world")
125
+ @idom.component
126
+ def World():
127
+ return idom.html.h1(["world"])
128
+
129
+ generated_view_id = mount.add(None, World)
130
+ world_component_instance = multiview(generated_view_id)
124
131
125
132
Displaying ``root`` with the parameter ``view_id=hello_world_view_id`` will show
126
133
the message 'hello world'. Usually though this is achieved by connecting to the
@@ -141,28 +148,37 @@ def MultiView(view_id: str) -> Any:
141
148
142
149
143
150
class MultiViewMount :
151
+ """Mount point for :func:`multiview`"""
144
152
145
153
__slots__ = "_next_auto_id" , "_views"
146
154
147
155
def __init__ (self , views : Dict [str , ComponentConstructor ]):
148
156
self ._next_auto_id = 0
149
157
self ._views = views
150
158
151
- def remove (self , view_id : str ) -> None :
152
- del self ._views [view_id ]
153
-
154
- def __getitem__ (self , view_id : str ) -> Callable [[ComponentConstructor ], str ]:
155
- def mount (constructor : ComponentConstructor ) -> str :
156
- self ._views [view_id ] = constructor
157
- return view_id
158
-
159
- return mount
160
-
161
- def __call__ (self , constructor : ComponentConstructor ) -> str :
162
- self ._next_auto_id += 1
163
- view_id = str (self ._next_auto_id )
159
+ def add (self , view_id : Optional [str ], constructor : ComponentConstructor ) -> str :
160
+ """Add a component constructor
161
+
162
+ Parameters:
163
+ view_id:
164
+ The view ID the constructor will be associated with. If ``None`` then
165
+ a view ID will be automatically generated.
166
+ constructor:
167
+ The component constructor to be mounted. It must accept no arguments.
168
+
169
+ Returns:
170
+ The view ID that was assocaited with the component - most useful for
171
+ auto-generated view IDs
172
+ """
173
+ if view_id is None :
174
+ self ._next_auto_id += 1
175
+ view_id = str (self ._next_auto_id )
164
176
self ._views [view_id ] = constructor
165
177
return view_id
166
178
179
+ def remove (self , view_id : str ) -> None :
180
+ """Remove a mounted component constructor given its view ID"""
181
+ del self ._views [view_id ]
182
+
167
183
def __repr__ (self ) -> str :
168
184
return f"{ type (self ).__name__ } ({ self ._views } )"
0 commit comments