Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ This repository contains examples of how to build application functionalities in
3. [Create a JSON editor for a Pydantic model](examples/pydantic_monaco)
4. [Conditionally rendering elements](examples/conditional_rendering)
5. [Conditionally disabling elements](examples/conditional_disabling)
6. [Creating a dialog](examples/dialog)
7. [Changing Pydantic rules based on user input](examples/dynamic_pydantic_rules)
8. [Complex Pydantic rules](examples/complex_pydantic_rules)
9. [Selecting datafiles from the server](examples/data_selector)
10. [Downloading files to the user's computer](examples/downloading_files)
11. [Running a Galaxy tool](examples/run_galaxy_tool)
12. [Running a Galaxy workflow](examples/run_galaxy_workflow)
13. [Working with Plotly](examples/plotly)
14. [Working with Matplotlib](examples/matplotlib)
15. [Working with VTK](examples/vtk)
16. [Synchronizing changes between tabs](examples/multitab)
6. [Disabling an element when the user interface has errors](examples/form_disabling)
7. [Creating a dialog](examples/dialog)
8. [Changing Pydantic rules based on user input](examples/dynamic_pydantic_rules)
9. [Complex Pydantic rules](examples/complex_pydantic_rules)
10. [Selecting datafiles from the server](examples/data_selector)
11. [Downloading files to the user's computer](examples/downloading_files)
12. [Running a Galaxy tool](examples/run_galaxy_tool)
13. [Running a Galaxy workflow](examples/run_galaxy_workflow)
14. [Working with Plotly](examples/plotly)
15. [Working with Matplotlib](examples/matplotlib)
16. [Working with VTK](examples/vtk)
17. [Synchronizing changes between tabs](examples/multitab)

We also provide examples that take advantage of ORNL resources:

Expand Down
2 changes: 1 addition & 1 deletion examples/complex_pydantic_rules/view_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ViewModel:
def __init__(self, model: Model, binding: BindingInterface) -> None:
self.model = model

# self.on_update is called any time the view updates the binding.
# self.send_cleaned_text_to_view is called any time the view updates the binding.
self.form_data_bind = binding.new_bind(self.model.form, callback_after_update=self.send_cleaned_text_to_view)

def send_cleaned_text_to_view(self, results: Dict[str, Any]) -> None:
Expand Down
1 change: 0 additions & 1 deletion examples/conditional_disabling/view_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class ViewModel:
def __init__(self, model: Model, binding: BindingInterface) -> None:
self.model = model

# self.on_update is called any time the view updates the binding.
self.form_data_bind = binding.new_bind(self.model.form)

def update_form_data(self) -> None:
Expand Down
1 change: 0 additions & 1 deletion examples/conditional_rendering/view_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class ViewModel:
def __init__(self, model: Model, binding: BindingInterface) -> None:
self.model = model

# self.on_update is called any time the view updates the binding.
self.form_data_bind = binding.new_bind(self.model.form)

def toggle_comments(self) -> None:
Expand Down
1 change: 0 additions & 1 deletion examples/dynamic_pydantic_rules/view_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class ViewModel:
def __init__(self, model: Model, binding: BindingInterface) -> None:
self.model = model

# self.on_update is called any time the view updates the binding.
self.form_data_bind = binding.new_bind(self.model.form)

def update_form_data(self) -> None:
Expand Down
5 changes: 5 additions & 0 deletions examples/form_disabling/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Entrypoint."""

from .main import main

main()
12 changes: 12 additions & 0 deletions examples/form_disabling/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Runs the form disabling example."""

from examples.form_disabling.view import App


def main() -> None:
app = App()
app.server.start(open_browser=False)


if __name__ == "__main__":
main()
17 changes: 17 additions & 0 deletions examples/form_disabling/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Model implementation for form disabling example."""

from pydantic import BaseModel, Field


class FormData(BaseModel):
"""Pydantic model for the form data."""

num_banks: int = Field(default=1, ge=1, le=10, title="Number of Banks [1, 10]")
wavelength: float = Field(default=0.1, ge=0.1, le=1.0, title="Wavelength [0.1, 1.0]")


class Model:
"""Model implementation for form disabling example."""

def __init__(self) -> None:
self.form = FormData()
54 changes: 54 additions & 0 deletions examples/form_disabling/view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""View for form disabling example."""

from nova.mvvm.trame_binding import TrameBinding
from nova.trame import ThemedApp
from nova.trame.view.components import InputField
from nova.trame.view.layouts import GridLayout, VBoxLayout
from trame.widgets import vuetify3 as vuetify

from .model import Model
from .view_model import ViewModel


class App(ThemedApp):
"""View for form disabling example."""

def __init__(self) -> None:
super().__init__()

self.create_vm()
# If you forget to call connect, then the application will crash when you attempt to update the view.
self.view_model.form_data_bind.connect("data")

self.create_ui()

def create_ui(self) -> None:
self.set_theme("CompactTheme")

with super().create_ui() as layout:
with layout.pre_content:
vuetify.VBanner(
"The form is in an error state.",
v_if="data?.pydantic_errors?.length > 0",
color="error",
icon="mdi-close",
)

with layout.content:
with GridLayout(classes="mb-2", columns=2, gap="0.5em"):
InputField(v_model="data.num_banks")
InputField(v_model="data.wavelength")
with VBoxLayout(halign="center"):
vuetify.VBtn(
"{{ data?.pydantic_errors?.length > 0 ? 'Errors Present' : 'No Errors' }}",
disabled=("data?.pydantic_errors?.length > 0",),
)

with layout.post_content:
vuetify.VAlert("{{ data?.pydantic_errors }}", v_if="data?.pydantic_errors?.length > 0", color="error")

def create_vm(self) -> None:
binding = TrameBinding(self.state)

model = Model()
self.view_model = ViewModel(model, binding)
18 changes: 18 additions & 0 deletions examples/form_disabling/view_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""View model implementation for form disabling example."""

from nova.mvvm.interface import BindingInterface

from .model import Model


class ViewModel:
"""View model implementation for form disabling example."""

def __init__(self, model: Model, binding: BindingInterface) -> None:
self.model = model

self.form_data_bind = binding.new_bind(self.model.form)

def update_form_data(self) -> None:
# This will fail if you haven't called connect on the binding!
self.form_data_bind.update_in_view(self.model.form)
2 changes: 1 addition & 1 deletion examples/multitab/view_model/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class InputViewModel:
def __init__(self, model: InputModel, binding: BindingInterface) -> None:
self.model = model

# self.on_update is called any time the view updates the binding.
# self.update_stats is called any time the view updates the binding.
self.inputs_bind = binding.new_bind(self.model.inputs, callback_after_update=self.update_stats)

# To communicate changes in this view model to other view models, we can create an event.
Expand Down
Loading