From 0e9f650e69ea8597cc90a872348005e62219c9a9 Mon Sep 17 00:00:00 2001 From: Joseph Burkhart <61951318+josephburkhart@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:40:38 -0500 Subject: [PATCH] A couple of small improvements to the custom vue component example (#4229) Hi there, this is my first PR for this project and I'm somewhat new to collaborative Open Source development, so please be patient. ### Description This PR modifies the Custom Vue Component [example](https://github.com/zauberzeug/nicegui/tree/main/examples/custom_vue_component) to make it a bit more helpful for developers who need to create custom components but haven't used Vue before. ### Motivation In the example linked above, the Vue component is defined in `counter.js`. This way of bundling a component in a vanilla JavaScript file is obviously supported by Vue, since every built-in NiceGUI component is defined this way, but the official Vue documentation (and basically every other resource on the web) assumes that developers are writing `.vue` files, which are supported by additional tooling. I think the example should structure its Vue code in a way that makes it easier for new developers to understand how it works in relation to existing Vue documentation. ### Changes In the new modified example, the python class definition now uses a new file, `counter.vue`, which re-implements `counter.js` in the more customary Vue Single-File Component format. The call to `ui.run()` has been modified to ensure browser reload on changes to the `.js` and `.vue` files, which is important for iterative development on the Vue side. ### Testing These changes do not add any new functionality that needs to be covered by tests. I have run the modified example and ensured that it does not error. ### Additional Notes I am curious if the developers would be interested in adding a second, more advanced custom vue component example. I am in the process of creating a pannable and zoomable image component, which I would be happy to wrap up in a nice example and provide in a separate PR. --------- Co-authored-by: Falko Schindler --- examples/custom_vue_component/README.md | 21 ++++++++++++ examples/custom_vue_component/counter.js | 13 ++++---- examples/custom_vue_component/main.py | 17 +++++----- examples/custom_vue_component/on_off.py | 14 ++++++++ examples/custom_vue_component/on_off.vue | 41 ++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 examples/custom_vue_component/README.md create mode 100644 examples/custom_vue_component/on_off.py create mode 100644 examples/custom_vue_component/on_off.vue diff --git a/examples/custom_vue_component/README.md b/examples/custom_vue_component/README.md new file mode 100644 index 000000000..820a26157 --- /dev/null +++ b/examples/custom_vue_component/README.md @@ -0,0 +1,21 @@ +# Custom Vue Component + +This example demonstrates how to create and use custom Vue components in NiceGUI. +One component is implemented using JavaScript, the other using Vue's Single-File Component (SFC) syntax. + +## Counter Component (counter.js) + +The `Counter` component is a simple counter that increments a value. +On change, it emits an event with the new value. +A reset method allows to reset the counter to 0. + +The JavaScript code in `counter.js` defines the front-end logic of the component using JavaScript. + +## OnOff Component (on_off.vue) + +The `OnOff` component is a simple toggle that switches between on and off. +On change, it emits an event with the new value. +A reset method is also provided to reset the toggle to off. + +The Single-File Component in `on_off.vue` defines the front-end logic of the component using Vue 2. +In contrast to the JavaScript code in `counter.js`, it splits the template, script, and style into separate sections. diff --git a/examples/custom_vue_component/counter.js b/examples/custom_vue_component/counter.js index 16b40fd16..f005a9920 100644 --- a/examples/custom_vue_component/counter.js +++ b/examples/custom_vue_component/counter.js @@ -1,9 +1,13 @@ // NOTE: Make sure to reload the browser with cache disabled after making changes to this file. export default { template: ` - `, + + `, + props: { + title: String, + }, data() { return { value: 0, @@ -18,7 +22,4 @@ export default { this.value = 0; }, }, - props: { - title: String, - }, }; diff --git a/examples/custom_vue_component/main.py b/examples/custom_vue_component/main.py index bd373eecf..f6b104629 100755 --- a/examples/custom_vue_component/main.py +++ b/examples/custom_vue_component/main.py @@ -1,17 +1,16 @@ #!/usr/bin/env python3 from counter import Counter +from on_off import OnOff from nicegui import ui -ui.markdown(''' -#### Try the new click counter! +with ui.row(align_items='center'): + counter = Counter('Count', on_change=lambda e: ui.notify(f'The value changed to {e.args}.')) + ui.button('Reset', on_click=counter.reset).props('outline') -Click to increment its value. -''') -with ui.card(): - counter = Counter('Clicks', on_change=lambda e: ui.notify(f'The value changed to {e.args}.')) +with ui.row(align_items='center'): + on_off = OnOff('State', on_change=lambda e: ui.notify(f'The value changed to {e.args}.')) + ui.button('Reset', on_click=on_off.reset).props('outline') -ui.button('Reset', on_click=counter.reset).props('small outline') - -ui.run() +ui.run(uvicorn_reload_includes='*.py,*.js,*.vue') diff --git a/examples/custom_vue_component/on_off.py b/examples/custom_vue_component/on_off.py new file mode 100644 index 000000000..90328b8a8 --- /dev/null +++ b/examples/custom_vue_component/on_off.py @@ -0,0 +1,14 @@ +from typing import Callable, Optional + +from nicegui.element import Element + + +class OnOff(Element, component='on_off.vue'): + + def __init__(self, title: str, *, on_change: Optional[Callable] = None) -> None: + super().__init__() + self._props['title'] = title + self.on('change', on_change) + + def reset(self) -> None: + self.run_method('reset') diff --git a/examples/custom_vue_component/on_off.vue b/examples/custom_vue_component/on_off.vue new file mode 100644 index 000000000..f5d91b1d5 --- /dev/null +++ b/examples/custom_vue_component/on_off.vue @@ -0,0 +1,41 @@ + + + + +