Introduction
The following release introduces two minor, backward-compatible changes. The first change allows users to add attributes to page wrapper div:
Adding Attributes to Pages
The updated implementation now allows adding class names for styling purposes:
Users can specify class names for the pages when configuring the router:
Layout
Support for higher-order components will remain unchanged. However, this release introduces a custom app hydration method called hydrate_app_layou
, for the hydration of the app and pages.
For example, consider this layout: nav → page content → footer. Using higher-order components and pages, this results in the following structure, using @Reuseable
on nav component, footer and passing new instance for each page will yield the expected behavior but with html redundancy :
<div>
<div data-zenaura="72e7e09f" hidden="">
<nav></nav>
<div>content</div>
<footer></footer>
</div>
<div data-zenaura="72e7e09f" hidden="">
<nav></nav>
<div>content</div>
<footer></footer>
</div>
<div data-zenaura="72e7e09f" hidden="">
<nav></nav>
<div>content</div>
<footer></footer>
</div>
</div>
Solution
Instead of users passing the router class to the build process, they now use ZenauraServer.hydrate_app_layout
, which allows them to pass multiple components and a list of pages in the order they want them to be rendered. Here is an example using higher-order components:
from zenaura.client.app import Route, App
from zenaura.client.page import Page
from public.routes import ClientRoutes
from public.components.header import Header
from public.components.intro import IntroSection
from public.components.footer import Footer
from public.components.examples import Example
nav_bar_header = Header(router)
intro_section = IntroSection()
footer = Footer()
example = Example()
# Higher-order component
def AppLayout(page_children):
return [
nav_bar_header,
*page_children,
footer,
]
# App and routing
home_page = Page(AppLayout([intro_section]))
router.add_route(Route(
title="components",
path=ClientRoutes.components.value,
page=components_page
))
This approach is now replaced with:
from zenaura.client.app import Route, App
from zenaura.client.page import Page
from zenaura.client.layout import Layout # Change
from public.routes import ClientRoutes
from public.components.header import Header
from public.components.intro import IntroSection
from public.components.footer import Footer
from public.components.examples import Example
nav_bar_header = Header(router)
intro_section = IntroSection()
footer = Footer()
example = Example()
# No higher-order component needed
# App and routing
home_page = Page([intro_section])
example_page = Page([example])
router.add_route(Route(
title="Developer-Focused | Zenaura",
path=ClientRoutes.home.value,
page=home_page
))
router.add_route(Route(
title="example",
path=ClientRoutes.examples.value,
page=example_page
))
# Adding app layout
my_app_layout = Layout(
top= [nav_bar_header], # first child component to root div
routes=app.routes, # Pages stored here
bottom=[footer] # last child components to root div
)
Updating build.py
:
from public.main import my_app_layout
ZenauraServer.hydrate_app_layout(my_app_layout, scripts=[
'<link rel="stylesheet" href="public/gigavolt.min.css">',
'<link rel="stylesheet" href="public/output.css">',
'<script src="public/highlight.min.js"></script>',
'<script src="public/python.min.js"></script>',
'<script>hljs.highlightAll();</script>',
"""
<script>
const ws = new WebSocket("ws://localhost:5000/refresh");
ws.onmessage = () => {
console.log("Reloading...");
location.reload();
};
</script>
"""
])
This change ensures that global components are included within the root div, not within every page: