-
-
Notifications
You must be signed in to change notification settings - Fork 525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mature intermediate tutorials #6466
Conversation
@@ -1,15 +1,14 @@ | |||
# Structure with a DataStore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will follow up in a new PR.
def styles(font_size): | ||
return {"font-size": f"{font_size}px"} | ||
|
||
styles_rx = pn.rx(styles)(intslider) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a a small hint what rx(something01)(something02) does? I have not seen the () () notation with .rx before (but maybe it's obvious to most people?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pn.rx(some_func)(something1, something2)
can be used as pn.bind(some_func, something1, something2)
and is the same as pn.bind(some_func, something1, something2).rx()
.
Its introduced and used in the basic tutorial https://holoviz-dev.github.io/panel/tutorials/basic/pn_rx.html. That is why I don't explain it here.
|
||
:::{note} | ||
|
||
`pn.bind` is the predecessor of `pn.rx`. We recommend using `pn.rx` over `pn.bind` as it's much more flexible and efficient. We include this example because you will find lots of examples in the Panel documentation and in the Panel community using `pn.bind`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or rather pn.rx is the successor of
pn.bind`.? This is good to know by the way, I did not realize this before. Is there a separate section somewhere regarding this in the docs (starting with the pn.bind) documentation?
Something that says at the top: We recommend pn.rx instead of pn.bind from now on? And a link to a migration tutorial that covers most cases of how best to change existing code that uses pn.bind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I will have to update that. We discussed this at HoloViz meeting today and we are not really ready to recommend transition yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, still interesting to know that that is the direction going forward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice tutorial @MarcSkovMadsen ! Made 2 small comments, not vital.
I would like to add Todo project using intermediate techniques. Here is my code. It almost works. Codefrom typing import Callable
import param
import panel as pn
pn.extension(sizing_mode="stretch_width", design="material")
BUTTON_WIDTH = 125
class Task(pn.viewable.Viewer):
value: str = param.String()
completed: bool = param.Boolean()
remove: bool = param.Event()
def __panel__(self):
completed = pn.widgets.Checkbox.from_param(self.param.completed, name="", align="center", sizing_mode="fixed")
content = pn.pane.Markdown(object=self.param.value)
remove = pn.widgets.Button.from_param(self.param.remove, width=BUTTON_WIDTH, icon="trash", sizing_mode="fixed")
return pn.Row(completed, content, remove, sizing_mode="stretch_width")
class TaskInput(pn.viewable.Viewer):
value = param.ClassSelector(class_=Task)
def _no_value(self, value):
return not bool(value)
def __panel__(self):
text_input = pn.widgets.TextInput(name="Task", placeholder="Enter a task")
text_input_has_value = pn.rx(self._no_value)(text_input.param.value_input)
submit_task = pn.widgets.Button(
name="Add",
align="center",
button_type="primary",
width=BUTTON_WIDTH,
sizing_mode="fixed",
disabled=text_input_has_value,
)
@pn.depends(text_input, submit_task, watch=True)
def clear_text_input(value, submit_task):
if text_input.value:
self.value = Task(value=text_input.value)
text_input.value=text_input.value_input=""
return pn.Row(
text_input, submit_task
)
class TaskList(pn.viewable.Viewer):
tasks = param.List()
remove_all_tasks = param.Event(label="Remove All")
def __init__(self, **params):
super().__init__(**params)
for task in self.tasks:
def remove(_, task=task):
self.tasks = [item for item in self.tasks if not item==task]
pn.bind(remove, task.param.remove, watch=True)
pn.bind(self._handle_done_changed, task.param.completed, watch=True)
self._llayout = pn.Column()
def _remove_task(self, *args):
task=args[0]
self.tasks = [item for item in self.tasks if not item==task]
def _remove_all_tasks(self, *args):
self.clear()
def _add_task(self, task):
def remove(_, task=task):
self.tasks = [item for item in self.tasks if not item==task]
pn.bind(remove, task.param.remove, watch=True)
self.tasks = [*self.tasks, task]
return task
@pn.depends("remove_all_tasks", watch=True)
def _handle_remove_all_tasks(self):
self.tasks=[]
def _handle_done_changed(self, completed):
self.param.trigger("tasks")
@param.depends("tasks")
def _layout(self):
self._llayout[:]=self.tasks
return self._llayout
@param.depends("tasks")
def status_report(self):
total_tasks = len(self.tasks)
completed_tasks = sum(task.completed for task in self.tasks)
return f"{completed_tasks} of {total_tasks} tasks completed"
@param.depends("tasks")
def _has_tasks(self):
return len(self.tasks)>0
def __panel__(self):
task_input = TaskInput()
pn.bind(self._add_task, task_input.param.value, watch=True)
clear = pn.widgets.Button.from_param(
self.param.remove_all_tasks,
button_type="primary",
button_style="outline",
width=BUTTON_WIDTH,
sizing_mode="fixed",
visible=self._has_tasks,
)
return pn.Column(
"## WTG Task List",
self.status_report,
task_input,
self._layout,
pn.Row(pn.Spacer(), clear),
max_width=500,
)
tasks = [
Task(value="Inspect the blades"),
Task(value="Inspect the nacelle"),
Task(value="Tighten the bolts"),
]
task_list = TaskList(tasks=tasks)
task_list.servable() |
pre-commit.ci autofix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again merging as-is and following up with review in my final review (hopefully over the weekend).
No description provided.