### Running PuePy Examples Locally Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/00-using-this-tutorial.md Clone the PuePy git repository and use a local web server to run the tutorial examples. Changes made to the example files will be reflected live in the browser upon reloading. ```bash git clone https://github.com/kkinder/puepy cd puepy python -m http.server 8000 ``` -------------------------------- ### Install Puepy Router Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Install the router by calling `app.install_router`. Choose a `link_mode` to define how URLs are created and parsed. ```Python from puepy import Application from puepy.router import Router app = Application() app.install_router(Router, link_mode=Router.LINK_MODE_HASH) ``` -------------------------------- ### Install PuePy Router with History Mode Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Demonstrates how to install the PuePy router using HTML5 history mode instead of hash-based routing. This is an alternative configuration for routing. ```python app.install_router(Router, link_mode=Router.LINK_MODE_HISTORY) ``` -------------------------------- ### Install PuePy Router with Hash Mode Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Installs the PuePy router using hash-based navigation. This is the default and recommended mode for most SPAs. ```python app.install_router(Router, link_mode=Router.LINK_MODE_HASH) ``` -------------------------------- ### Full Example: Parsing HTML with BeautifulSoup Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/08-pypi-libraries.md This is a complete example demonstrating how to use BeautifulSoup to parse HTML and generate a PuePy component. It requires the CPython/Pyodide runtime and the 'beautifulsoup4' package. ```python # This file is generated from examples/tutorial/08_libraries/libraries.py # It is not intended to be run directly. # The actual code is embedded in the documentation. # For the full example, please refer to the source file. # Example content: # from bs4 import BeautifulSoup, Comment # # html_doc = """ # The Dormouse's story #

The Dormouse's story

# #

Once upon a time there were three little sisters; and their names were # Elsie, # Lacie and # Tillie; # and they lived at the bottom of a well.

# #

...

# # # # # """ # # soup = BeautifulSoup(html_doc, 'html.parser') # # # Extract title # title = soup.title.string # # # Extract first paragraph # first_paragraph = soup.find('p', class_='story').get_text() # # # Extract all links # links = [a['href'] for a in soup.find_all('a')] # # # Extract comments # comments = [str(c) for c in soup.find_all(Comment)] # # # Construct PuePy component # puepy_component = f""" #
#

HTML Parsing Example

#

Title: {title}

#

First Paragraph: {first_paragraph}

#

Links:

# #

Comments:

# #
# """ # # # In a real PuePy application, you would typically render this component # # For demonstration purposes, we'll just print it. # print(puepy_component) ``` -------------------------------- ### Python: In-place State Modification Example (Will Not Work) Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/02-hello-name.md Illustrates incorrect methods for modifying complex state objects like lists and dictionaries in Puepy, which do not trigger re-renders. ```python # THESE WILL NOT WORK: self.state["my_list"].append("spam") self.state["my_dict"]["spam"] = "eggs" ``` -------------------------------- ### Shoelace Spinner Loading Indicator Source: https://github.com/kkinder/puepy/blob/main/docs/cookbook/loading-indicators.md Integrate a Shoelace web component spinner for a visual loading indicator. This example shows how to set up the necessary links and scripts, and embed the spinner within the target element. ```html Example
``` -------------------------------- ### Create a Basic PuePy Application Source: https://github.com/kkinder/puepy/blob/main/README.md This snippet demonstrates the fundamental structure of a PuePy application. It includes setting up the Application, defining a Page with initial state, populating the UI with elements, and handling user interactions like button clicks. Mount the application to a specific DOM element. ```python from puepy import Page, Application, t app = Application() @app.page() class Hello(Page): def initial(self): return dict(name="") def populate(self): with t.div(classes=["container", "mx-auto", "p-4"]): t.h1("Welcome to PyScript", classes=["text-xl", "pb-4"]) if self.state["name"]: t.p(f"Hello there, {self.state['name']}") else: t.p("Why don't you tell me your name?") t.input(placeholder="Enter your name", bind="name") t.button("Continue", classes="btn btn-lg", on_click=self.on_button_click) def on_button_click(self, event): print("Button clicked") # This logs to console app.mount("#app") ``` -------------------------------- ### Download PuePy Client Runtime Source: https://github.com/kkinder/puepy/blob/main/docs/installation.md Use this command to download the PuePy wheel file for client-side integration. Ensure you replace {{project_version}} with the correct version number. ```Bash curl -O https://download.puepy.dev/puepy-{{project_version}}-py3-none-any.whl ``` -------------------------------- ### Load Pyodide Runtime Source: https://github.com/kkinder/puepy/blob/main/docs/guide/runtimes.md Use this configuration to load the Pyodide runtime. Ensure your `pyscript.json` configuration is set up correctly. ```html ``` -------------------------------- ### PuePy Hello World Python Code Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/01-hello-world.md This Python script defines a simple PuePy application. It imports necessary components, creates an application instance, defines a page with content, and mounts the application to a specific DOM element. ```python from puepy import Application, Page, t ``` ```python app = Application() ``` ```python class HelloWorldPage(Page): def populate(self): self.add(t.h1(t.text("Hello, World!"))) ``` ```python app.mount("#app", HelloWorldPage) ``` -------------------------------- ### Python: Hello Name Page with State Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/02-hello-name.md Defines a Puepy page that initializes state with a 'name' variable, conditionally displays a greeting based on the name, and binds an input field to the 'name' state. ```python from puepy import Application, Page, t app = Application() @app.page() class HelloNamePage(Page): def initial(self): return {"name": ""} # (1) def populate(self): if self.state["name"]: # (2) t.h1(f"Hello, {self.state['name']}!") else: t.h1(f"Why don't you tell me your name?") with t.div(style="margin: 1em"): t.input(bind="name", placeholder="name", autocomplete="off") # (3) app.mount("#app") ``` -------------------------------- ### Compare HTML Template to Puepy Python Code Source: https://github.com/kkinder/puepy/blob/main/docs/faq.md Illustrates how a simple HTML structure with a loop and a button can be represented more concisely in Puepy's Python syntax. ```html

{{ name }}'s grocery shopping list

``` ```python with t.h1(): t(f"{name}'s grocery shopping list") with t.ul(): for item in items: t.li(item) t.button("Buy Items", on_click=self.buy) ``` -------------------------------- ### Define Initial Component State Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Components define their initial state using the `initial()` method, returning a dictionary of state properties. ```Python class MyComponent(Component): def initial(self): return { "name": "Monty ... Something?", "movies": ["Monty Python and the Holy Grail"] } ``` -------------------------------- ### Python: Correct In-place State Modification with Mutate Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/02-hello-name.md Demonstrates the correct way to modify complex state objects in Puepy using the `with self.state.mutate()` context manager to ensure re-renders. ```python # This will work with self.state.mutate("my_list", "my_dict"): self.state["my_list"].append("spam") self.state["my_dict"]["spam"] = "eggs" ``` -------------------------------- ### HTML Structure for PuePy Application Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/01-hello-world.md This HTML file sets up the basic structure for a PuePy application. It includes PyScript from a CDN and specifies the configuration file and the main Python script to execute. ```html ``` ```html ``` -------------------------------- ### Define Page with Route Parameters Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Pages can accept parameters from the router. Define placeholders in the route path and list them in the `props` attribute of the Page class. ```Python @app.page("/post///view") class PostPage(Page): props = ["author_id", "post_id"] def populate(self): t.p(f"This is a post from {self.author_id}->{self.user_id}") ``` -------------------------------- ### Mount the PuePy Application Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Mounts the PuePy application to the specified DOM element, typically an element with the ID 'app'. This makes the application interactive. ```python app.mount("#app") ``` -------------------------------- ### Define the Default Page with Pet Links Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Defines the default page for the root URL. It displays a list of pets, with each pet name linking to its respective detail page using the custom `Link` component and passing the `pet_id` as an argument. ```python @app.page() class DefaultPage(Page): def populate(self): t.h1("PuePy Routing Demo: Pet Listing") with t.ul(): for pet_id, pet_details in pets.items(): with t.li(): t.link(pet_details["name"], href=PetPage, args={"pet_id": pet_id}) # (5) ``` -------------------------------- ### Using Shoelace Dialog and Button Components in PuePy Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/09-using-web-components.md This Python code demonstrates how to use Shoelace's `sl-dialog` and `sl-button` Web Components within a PuePy page. It shows how to define the components and attach event handlers for opening and closing the dialog. ```Python @app.page() class DefaultPage(Page): def populate(self): with t.sl_dialog(label="Dialog", classes="dialog-overview", tag="sl-dialog", ref="dialog"): # (1)! t("Web Components are just delightful.") t.sl_button("Close", slot="footer", variant="primary", on_click=self.on_close_click) # (2)! t.sl_button("Open Dialog", tag="sl-button", on_click=self.on_open_click) ``` ```Python def on_open_click(self, event): self.refs["dialog"].element.show() def on_close_click(self, event): self.refs["dialog"].element.hide() ``` -------------------------------- ### Use the Card Component with Slots and Events Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/06-components.md This snippet demonstrates how to use the previously defined `Card` component within a Puepy page. It shows how to pass props, populate named and default slots, and handle custom events emitted by the component. ```python @app.page() class ComponentPage(Page): def initial(self): return {"message": ""} def populate(self): t.h1("Components are useful") with t.card(type="success", on_my_custom_event=self.handle_custom_event) as card: with card.slot("card-header"): t("Success!") with card.slot(): t("Your operation worked") with t.card(type="warning", on_my_custom_event=self.handle_custom_event) as card: with card.slot("card-header"): t("Warning!") with card.slot(): t("Your operation may not work") with t.card(type="error", on_my_custom_event=self.handle_custom_event) as card: with card.slot("card-header"): t("Failure!") with card.slot(): t("Your operation failed") if self.state["message"]: t.p(self.state["message"]) def handle_custom_event(self, event): self.state["message"] = f"Custom event from card with type {event.detail.get('type')}" ``` -------------------------------- ### Consuming Slots Correctly Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/06-components.md Illustrates the correct way to consume slots by calling `.slot` directly on the component instance, not `t.slot` or `self.slot`. ```py with t.card() as card: with card.slot("card-header"): # (1) t("Success!") ``` -------------------------------- ### Redirect to Login Page Source: https://github.com/kkinder/puepy/blob/main/docs/cookbook/navigation-guards.md Implement a precheck to redirect users to a different page (e.g., a login page) if they do not meet the required conditions for accessing the current page. ```python from puepy import exceptions, Page class LoginPage(Page): ... class MyPage(Page): ... def precheck(self): if not self.application.state["authenticated_user"]: raise exceptions.Redirect(LoginPage) ``` -------------------------------- ### Configure PuePy Runtime in PyScript Source: https://github.com/kkinder/puepy/blob/main/docs/guide/pyscript-config.md Use this JSON configuration to set up the PuePy runtime within a PyScript project. It specifies the project name, enables debug mode, includes the PuePy wheel file, and loads the Morphdom JavaScript module. ```JSON { "name": "PuePy Tutorial", "debug": true, "packages": [ "./puepy-{{project_version}}-py3-none-any.whl" ], "js_modules": { "main": { "https://cdn.jsdelivr.net/npm/morphdom@2.7.4/+esm": "morphdom" } } } ``` -------------------------------- ### Configure PyScript to use CPython/Pyodide runtime Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/08-pypi-libraries.md Specify the CPython/Pyodide runtime for PyScript by setting the script type to 'py'. This enables the use of a wider range of Python packages. ```html ``` -------------------------------- ### Configure PyScript for Multiple Files Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/10-full-app.md Specify additional Python source files and JavaScript modules in the PyScript configuration to make them available to your application. Ensure correct paths and module names for successful integration. ```json { "name": "PuePy Tutorial", "debug": true, "files": { "./common.py": "common.py", "./components.py": "components.py", "./main.py": "main.py", "./pages.py": "pages.py" }, "js_modules": { "main": { "https://cdn.jsdelivr.net/npm/chart.js": "chart", "https://cdn.jsdelivr.net/npm/morphdom@2.7.4/+esm": "morphdom" } }, "packages": [ "../../puepy-{{project_version}}-py3-none-any.whl" ] } ``` -------------------------------- ### Loading Shoelace Web Components from CDN Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/09-using-web-components.md Include these HTML tags in your index.html file to load the Shoelace library and its theme from a CDN. This makes Shoelace components available for use in your application. ```html ``` -------------------------------- ### Render Content Based on Application State Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Display a personalized greeting using the `authenticated_user` from the application state. ```python def populate(self): ... t.h1(f"Hello, you are authenticated as {self.application.state['authenticated_user']}") ``` -------------------------------- ### Define a Default Page Component Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Shows the basic structure for defining a default page component in PuePy. This page is rendered when no specific route matches or when the URL is the root. ```python @app.page() class DefaultPage(Page): ... ``` -------------------------------- ### Counter Component Styles Source: https://github.com/kkinder/puepy/blob/main/examples/tutorial/03_counter/index.html Basic CSS for styling the counter buttons and display. ```css body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .button-box { display: flex; gap: 10px; } .button { padding: 10px 20px; font-size: 16px; } .count { font-size: 16px; padding: 10px 20px; } .decrement-button { background-color: darkred; color: white; } .increment-button { background-color: darkgreen; color: white; } ``` -------------------------------- ### Watch for Specific State Changes Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Define an `on__change` method to execute custom logic when a specific state key's value is updated. ```Python class MyComponent(Component): def initial(): return {"spam": "eggs"} def on_spam_change(self, new_value): print("New value for spam", new_value) ``` -------------------------------- ### Simple HTML Loading Indicator Source: https://github.com/kkinder/puepy/blob/main/docs/cookbook/loading-indicators.md Include a simple HTML indicator within the target element. This text will be replaced by PuePy once it loads. ```html
Loading...
``` -------------------------------- ### Set Default Component Classes, Attributes, and Role Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Define `default_classes`, `default_attributes`, and `default_role` to apply consistent styling and behavior to component instances. ```python class MyInputComponent(Component): enclosing_tag = "input" default_classes = ["my-input"] default_attributes = {"type": "text"} default_role = "textbox" ``` -------------------------------- ### Component Parent/Child Relationships Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Demonstrates how to access parent and page instances from within a component. The `on_event_handle` method shows accessing `self.parent`. ```python from puepy import Application, Page, Component, t app = Application() @t.component() class CustomInput(Component): enclosing_tag = "input" def on_event_handle(self, event): print(self.parent) class MyPage(Page): def populate(self): with t.div(): t.custom_input() ``` -------------------------------- ### PyScript Configuration for PuePy Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/01-hello-world.md This JSON file configures PyScript for a PuePy application. It specifies the application name, enables debug mode, and lists necessary JavaScript modules and Python packages, including PuePy itself and its dependency, Morphdom. ```json { "name": "PuePy Tutorial", "debug": true, "files": {}, "js_modules": { "main": { "https://cdn.jsdelivr.net/npm/morphdom@2.7.4/+esm": "morphdom" } }, "packages": [ "./puepy-{{project_version}}-py3-none-any.whl" ] } ``` -------------------------------- ### Configure Redraw on App State Changes (Default) Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Sets `redraw_on_app_state_changes` to `True`, meaning all changes to application state will trigger a redraw by default. ```python class Page1(Page): redraw_on_app_state_changes = True # (1)! ``` -------------------------------- ### Fill Slots in Calling Code Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/06-components.md This snippet demonstrates how to fill defined slots in a component from the calling code using the context manager and the `.slot()` method. ```py with t.card() as card: with card.slot("card-header"): t("Success!") with card.slot(): t("Your operation worked") ``` -------------------------------- ### Loading Indicator HTML Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/10-full-app.md Displays a loading spinner within the target div while the application is initializing. This provides visual feedback to the user on slower connections. ```html
``` -------------------------------- ### Python App Layout Component Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/10-full-app.md Defines a reusable application layout component with a sidebar, header, and footer. Includes pre-authentication checks and navigation logic. ```Python class SidebarItem: def __init__(self, label, icon, route): self.label = label self.icon = icon self.route = route @t.component() class AppLayout(Component): sidebar_items = [ SidebarItem("Dashboard", "emoji-sunglasses", "dashboard_page"), SidebarItem("Charts", "graph-up", "charts_page"), SidebarItem("Forms", "input-cursor-text", "forms_page"), ] def precheck(self): if not self.application.state["authenticated_user"]: raise exceptions.Unauthorized() def populate(self): with t.sl_drawer(label="Menu", placement="start", classes="drawer-placement-start", ref="drawer"): self.populate_sidebar() with t.div(classes="container"): with t.div(classes="header"): with t.div(): with t.sl_button(classes="menu-btn", on_click=self.show_drawer): t.sl_icon(name="list") t.div("The Dapper App") self.populate_topright() with t.div(classes="sidebar", id="sidebar"): self.populate_sidebar() with t.div(classes="main"): self.insert_slot() with t.div(classes="footer"): t("Business Time!") def populate_topright(self): with t.div(classes="dropdown-hoist"): with t.sl_dropdown(hoist=""): t.sl_icon_button(slot="trigger", label="User Settings", name="person-gear") with t.sl_menu(on_sl_select=self.on_menu_select): t.sl_menu_item( "Profile", t.sl_icon(slot="suffix", name="person-badge"), value="profile", ) t.sl_menu_item("Settings", t.sl_icon(slot="suffix", name="gear"), value="settings") t.sl_divider() t.sl_menu_item("Logout", t.sl_icon(slot="suffix", name="box-arrow-right"), value="logout") def on_menu_select(self, event): if event.detail.item.value == "logout": self.application.state["authenticated_user"] = "" def populate_sidebar(self): for item in self.sidebar_items: with t.div(): with t.sl_button( item.label, variant="text", classes="sidebar-button", href=self.page.router.reverse(item.route), ): if item.icon: t.sl_icon(name=item.icon, slot="prefix") def show_drawer(self, event): self.refs["drawer"].element.show() ``` -------------------------------- ### Watch for Any State Change Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Implement the `on_state_change` method to be notified of any key-value pair changes in the component's state. ```Python class MyComponent(Component): def on_state_change(self, key, value): print(key, "was set to", value) ``` -------------------------------- ### Configure Redraw on Specific App State Changes Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Sets `redraw_on_app_state_changes` to a list of keys, triggering a redraw only when those specific keys in the application state change. ```python class Page3(Page): redraw_on_app_state_changes = ["authenticated_user"] # (3)! ``` -------------------------------- ### Counter Application with Event Handlers Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/03-events.md This Python code defines a Puepy application with a counter that can be incremented or decremented using buttons. It demonstrates binding click events to methods that modify the page's state. ```python from puepy import Application, Page, t app = Application() @app.page() class CounterPage(Page): def initial(self): return {"current_value": 0} def populate(self): with t.div(classes="button-box"): t.button("-", classes=["button", "decrement-button"], on_click=self.on_decrement_click) # (1) t.span(str(self.state["current_value"]), classes="count") t.button("+", classes="button increment-button", on_click=self.on_increment_click) # (2) def on_decrement_click(self, event): self.state["current_value"] -= 1 # (3) def on_increment_click(self, event): self.state["current_value"] += 1 # (4) app.mount("#app") ``` -------------------------------- ### Define a Reusable Card Component Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/06-components.md This snippet shows how to define a custom Puepy component named `Card`. It includes defining properties (`props`), CSS classes, and using slots for dynamic content insertion. The component also triggers a custom event upon button click. ```python @t.component() class Card(Component): props = ["type", "button_text"] card = CssClass( margin="1em", padding="1em", background_color="#efefef", border="solid 2px #333", ) default_classes = [card] type_styles = { "success": success, "warning": warning, "error": error, } def populate(self): with t.h2(classes=[self.type_styles[self.type]]): self.insert_slot("card-header") with t.p(): self.insert_slot() t.button(self.button_text, on_click=self.on_button_click) def on_button_click(self, event): self.trigger_event("my-custom-event", detail={"type": self.type}) ``` -------------------------------- ### Define a Dynamic Route for Pet Details Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md Defines a page component that displays information about a specific pet, identified by `pet_id` in the URL. It uses a dictionary to fetch pet details and includes a link back to the homepage. ```python @app.page("/pet/") # (3) class PetPage(Page): props = ["pet_id"] def populate(self): pet = pets.get(self.pet_id) t.h1("Pet Information") with t.dl(): for k, v in pet.items(): t.dt(k) t.dd(v) t.link("Back to Homepage", href=DefaultPage) # (4) ``` -------------------------------- ### Define Component Props Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Define props for a component using a list of strings for names or Prop instances for additional metadata. The expanded props are available on `self.props_expanded`. ```python class MyComponent(Component): props = [ "title", # (1)! Prop("author_name", "Name of Author", str, "Unknown") # (2)! ] ``` -------------------------------- ### Define a Default Route Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Define a default route by omitting the path argument in the `@app.page` decorator. This route will be matched if no other routes are specified. ```Python @app.page() class MyPage(Page): ... ``` -------------------------------- ### Custom Link Component for Navigation Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/07-routing.md A custom component for creating navigation links. It handles click events to prevent default navigation and uses the router to navigate to the specified page, resolving the correct href. ```python from puepy import Application, Page, Component, t from puepy.router import Router app = Application() app.install_router(Router, link_mode=Router.LINK_MODE_HASH) # (1) pets = { "scooby": {"name": "Scooby-Doo", "type": "dog", "character": "fearful"}, "garfield": {"name": "Garfield", "type": "cat", "character": "lazy"}, "snoopy": {"name": "Snoopy", "type": "dog", "character": "playful"}, } @t.component() class Link(Component): # (2) props = ["args"] enclosing_tag = "a" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_event_listener("click", self.on_click) def set_href(self, href): if issubclass(href, Page): args = self.args or {} self._resolved_href = self.page.router.reverse(href, **args) else: self._resolved_href = href self.attrs["href"] = self._resolved_href def on_click(self, event): if ( isinstance(self._resolved_href, str) and self._resolved_href[0] in "#/" and self.page.router.navigate_to_path(self._resolved_href) ): # A page was found; prevent navigation and navigate to page event.preventDefault() ``` -------------------------------- ### Insert Raw HTML in Puepy Component Source: https://github.com/kkinder/puepy/blob/main/docs/faq.md Shows how to embed raw HTML strings directly into a Puepy component's rendering using the `html()` helper function. Ensure the `html` function is imported from `puepy.core`. ```python from puepy.core import html class MyPage(Page): def populate(self): t(html("Hello!")) ``` -------------------------------- ### Define a Page Route with Decorator Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Use the `@app.page` decorator to associate a URL path with a Page class. This is the preferred method for defining routes. ```Python from puepy import Page @app.page("/my-page") class MyPage(Page): ... ``` -------------------------------- ### Reverse Route by Page Object Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Generate a URL path for a specific page by calling `self.page.router.reverse` with the Page object and any necessary arguments. ```Python path = self.page.router.reverse(PostPage, author_id="5", post_id="7") ``` -------------------------------- ### Assigning and Accessing Component Refs Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Use the `ref=` argument when building tags to assign a unique identifier. Access these refs later via `self.refs["ref_name"]` to interact with the component, such as triggering a click event. ```Python class MyPage(Page): def populate(self): t.button("My Button", ref="my_button") def auto_click_button(self, ...): self.refs["my_button"].element.click() ``` -------------------------------- ### Import BeautifulSoup from bs4 Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/08-pypi-libraries.md Import the BeautifulSoup library and any specific components like 'Comment' from the 'bs4' package in your Python source file. This makes the library's functionality available for use. ```python from bs4 import BeautifulSoup, Comment ``` -------------------------------- ### Raise Unauthorized Exception Source: https://github.com/kkinder/puepy/blob/main/docs/cookbook/navigation-guards.md Use this precheck to prevent page rendering and raise an Unauthorized exception if a condition (e.g., user not authenticated) is not met. Puepy will then display the unauthorized page. ```python from puepy import exceptions, Page class MyPage(Page): ... def precheck(self): if not self.application.state["authenticated_user"]: raise exceptions.Unauthorized() ``` -------------------------------- ### Listen for Custom Events Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Consume custom events emitted by child components by defining an `on_` method in the parent component or page. The event object contains the detail dictionary passed during the trigger. ```python class MyPage(Page): def populate(self): t.my_component(on_greeting=self.on_greeting_sent) def on_greeting_sent(self, event): print("Incoming message from component", event.detail.get('message')) ``` -------------------------------- ### Create a Chart Component with Chart.js Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/10-full-app.md Define a reusable Chart component in Python that integrates with the Chart.js JavaScript library. This component handles chart creation, updates, and destruction using PyScript's lifecycle methods. ```python @t.component() class Chart(Component): props = ["type", "data", "options"] enclosing_tag = "canvas" def on_redraw(self): self.call_chartjs() def on_ready(self): self.call_chartjs() def call_chartjs(self): if hasattr(self, "_chart_js"): self._chart_js.destroy() self._chart_js = js.Chart.new( self.element, jsobj(type=self.type, data=self.data, options=self.options), ) ``` -------------------------------- ### Bind Form Element to State Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Use the `bind` parameter on input elements to create a two-way connection between the element's value and a state key. Changes in the input update the state, and state updates reflect in the input. ```Python class MyComponent(Component): def initial(self): return {"name": ""} def populate(self): # bind specifies what key on self.state should be tied to this input's value t.input(placeholder="Type your name", bind="name") ``` -------------------------------- ### Set Authenticated User in Application State Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Assign the username from local state to the `authenticated_user` key in the application state. ```python self.application.state["authenticated_user"] = self.state["username"] ``` -------------------------------- ### Add or Remove Component CSS Classes Source: https://github.com/kkinder/puepy/blob/main/docs/guide/css-classes.md When using a component, you can add new classes or remove default classes. To remove a class, prefix its name with a '/'. ```Python t.card(classes="card-blue") t.card(classes="/card") ``` -------------------------------- ### PuePy Fixed Code: Using `ref=` for Element Preservation Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/04-refs.md This code shows the solution using the `ref=` parameter to preserve DOM elements between refreshes. This prevents elements from being discarded and recreated, maintaining their state and focus. ```python @app.page() class RefsSolutionPage(Page): def initial(self): return {"word": ""} def populate(self): t.h1("Solution: Use ref=") if self.state["word"]: for char in self.state["word"]: t.span(char, classes="char-box") with t.div(style="margin-top: 1em"): t.input(bind="word", placeholder="Type a word", ref="enter_word") ``` -------------------------------- ### Reverse Route by Route Name Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Alternatively, reverse a route by its name using `self.page.router.reverse`, providing the route name string and any required arguments. ```Python path = self.page.router.reverse("post_page", author_id="5", post_id="7") ``` -------------------------------- ### Add Chart.js JavaScript Library Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/10-full-app.md Include the Chart.js library in your PyScript project by specifying its CDN URL and a module name in the `js_modules` configuration. This allows direct usage from Python. ```json "https://cdn.jsdelivr.net/npm/chart.js": "chart" ``` -------------------------------- ### Specify PyPi packages in PyScript config Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/08-pypi-libraries.md Declare necessary PyPi packages, such as 'beautifulsoup4', in the 'packages' array within the PyScript JSON configuration file. This ensures the packages are available to your application. ```json { "name": "PuePy Tutorial", "debug": true, "packages": [ "./puepy-0.5.0-py3-none-any.whl", "beautifulsoup4" ], "js_modules": { "main": { "https://cdn.jsdelivr.net/npm/morphdom@2.7.4/+esm": "morphdom" } } } ``` -------------------------------- ### Check Authenticated User in Navigation Guard Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Use `application.state` to check for an authenticated user before allowing navigation. Raises `Unauthorized` if the user is not authenticated. ```python def precheck(self): if not self.application.state["authenticated_user"]: raise exceptions.Unauthorized() ``` -------------------------------- ### PuePy Problem Code: Re-creating DOM Elements Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/04-refs.md This code demonstrates the issue where DOM elements are re-created on each page redraw, leading to loss of focus. It's used when elements need to be dynamically generated without preservation. ```python @app.page() class RefsProblemPage(Page): def initial(self): return {"word": ""} def populate(self): t.h1("Problem: DOM elements are re-created") if self.state["word"]: for char in self.state["word"]: t.span(char, classes="char-box") with t.div(style="margin-top: 1em"): t.input(bind="word", placeholder="Type a word") ``` -------------------------------- ### Add Route Directly Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Routes can also be added directly to the router instance using `app.router.add_route`. This method is less preferred than using the decorator. ```Python app.router.add_route(path_match="/foobar", page_class=Foobar) ``` -------------------------------- ### Use SVG with xmlns in Puepy Source: https://github.com/kkinder/puepy/blob/main/docs/faq.md Demonstrates how to correctly include SVG elements within Puepy components by specifying the xmlns attribute. ```python with t.svg(xmlns="http://www.w3.org/2000/svg"): ... ``` -------------------------------- ### Configure Redraw on App State Changes (Disabled) Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Sets `redraw_on_app_state_changes` to `False`, preventing changes to application state from triggering a redraw. ```python class Page2(Page): redraw_on_app_state_changes = False # (2)! ``` -------------------------------- ### Modify Mutable State In-Place with Mutate Context Manager Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md When modifying mutable objects within the state (like lists or dictionaries) in-place, use the `mutate()` context manager to ensure reactivity. Direct in-place modifications without `mutate()` will not trigger UI updates. ```Python class MyComponent(Component): def update_movies(self): # THIS WILL NOT CAUSE A UI REFRESH! self.state["movies"].append("Monty Python’s Life of Brian") ``` ```Python class MyComponent(Component): def update_movies(self): # THIS WILL NOT CAUSE A UI REFRESH! with self.state.mutate("movies"): self.state["movies"].append("Monty Python’s Life of Brian") ``` -------------------------------- ### Define Slots in a Component Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/06-components.md This snippet shows how to define slots within a Puepy component using `self.insert_slot()`. The default slot is used when no name is provided. ```py with t.h2(): self.insert_slot("card-header") with t.p(): self.insert_slot() # (1) ``` -------------------------------- ### Limit Automatic UI Refresh Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Specify a list of state keys to `redraw_on_changes` to only refresh the UI when those specific items change. ```Python class MyComponent(Component): # When items in this this change, the UI will be redrawn redraw_on_changes = ["items"] ``` -------------------------------- ### Guessing Game with Number Watcher Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/05-watchers.md This snippet demonstrates a PuePy component that watches for changes in the 'number' input field. When the input changes, the `on_number_change` method is triggered to validate the user's guess against a predefined winning number and update a message accordingly. The function name `on_number_change` is automatically registered based on the pattern `on__change`. ```python from puepy import app, Page, t @app.page() class WatcherPage(Page): def initial(self): self.winner = 4 return {"number": "", "message": ""} def populate(self): t.h1("Can you guess a number between 1 and 10?") with t.div(style="margin: 1em"): t.input(bind="number", placeholder="Enter a guess", autocomplete="off", type="number", maxlength=1) if self.state["message"]: t.p(self.state["message"]) def on_number_change(self, event): # (1) try: if int(self.state["number"]) == self.winner: self.state["message"] = "You guessed the number!" else: self.state["message"] = "Keep trying..." except (ValueError, TypeError): self.state["message"] = "" ``` -------------------------------- ### Define Custom Route Name Source: https://github.com/kkinder/puepy/blob/main/docs/guide/advanced-routing.md Assign a custom name to a route using the `name` parameter in either the `@app.page` decorator or the `add_route` method. This name can be used for reversing routes. ```Python @app.page("/my-page", name="another_name") class MyPage(Page): ... class AnotherPage(Page): ... app.add_route("/foobar", AnotherPage, name="foobar") ``` -------------------------------- ### Component Default CSS Classes Source: https://github.com/kkinder/puepy/blob/main/docs/guide/css-classes.md Components can specify default CSS classes using the `default_classes` attribute. These classes are applied automatically when the component is rendered. ```Python @t.component() class Card(Component): ... default_classes = ["card"] ... ``` -------------------------------- ### Trigger Custom Events Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Emit custom events from a component using `self.trigger_event`, optionally including a detail dictionary. This allows child components to communicate with parent components. ```python class MyComponent(Component): def some_method(self): self.trigger_event("greeting", detail={"message": "Hello There"}) ``` -------------------------------- ### Pass Attributes to Components Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Arbitrary keyword arguments not matching defined props are treated as attributes and rendered as HTML attributes on the component's tag. This allows passing HTML attributes without explicit prop definition. ```python from puepy import Component, Page, t class NameInput(Component): enclosing_tag = "input" class MyPage(Page): def populate(self): t.name_input(id="name_input", placeholder="Enter your name") ``` -------------------------------- ### Accessing Web Component DOM Elements in PuePy Source: https://github.com/kkinder/puepy/blob/main/docs/tutorial/09-using-web-components.md This Python snippet shows how to access the underlying DOM element of a Web Component instance in PuePy. Use the `.element` attribute on the referenced component to call its native JavaScript methods, such as `show()`. ```Python self.refs["dialog"].element.show() ``` -------------------------------- ### Define CSS Classes for Tags Source: https://github.com/kkinder/puepy/blob/main/docs/guide/css-classes.md Use `class_name` or `classes` attributes to assign CSS classes to tags. Classes can be provided as a single string, a list of strings, or a dictionary where keys are class names and values determine inclusion. ```Python t.button("Primary Large Button", class_name="primary large") t.button("Primary Small Button", classes=["primary", "small"]) t.button("Primary Medium Button", classes={ "primary": True, "medium": True, "small": False, "large": False}) ``` -------------------------------- ### Override Component Enclosing Tag Source: https://github.com/kkinder/puepy/blob/main/docs/guide/in-depth-components.md Set the `enclosing_tag` attribute to change the default HTML tag used for rendering a component. The default is 'div'. ```python class MyInputComponent(Component): enclosing_tag = "input" ``` -------------------------------- ### Update Component State to Trigger Refresh Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Modifying the state dictionary directly, such as updating the 'name' property, automatically triggers a UI refresh. ```Python class MyComponent(Component): def update_name(self): # This triggers a refresh self.state["name"] = "Monty Python" ``` -------------------------------- ### Disable Automatic UI Refresh Source: https://github.com/kkinder/puepy/blob/main/docs/guide/reactivity.md Set `redraw_on_changes` to `False` to completely disable automatic UI refreshes. Use `trigger_redraw()` to manually refresh the component or the entire page. ```Python class MyComponent(Component): # The UI will no longer refresh on state changes redraw_on_changes = False def something_happened(self): # This can be called to manually refresh this component and its children self.trigger_redraw() # Or, you can redraw the whole page self.page.trigger_redraw() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.