On this tutorial, we construct a completely interactive, multi-page net software utilizing NiceGUI. We begin by establishing the setting and designing a reusable structure that features navigation, theming, and darkish mode assist. As we transfer ahead, we implement a dwell dashboard with real-time metrics and charts, demonstrating reactive bindings and timed updates. We then prolong the applying with a whole CRUD-based todo system, adopted by a validated kind with dialogs and consumer suggestions mechanisms. We additionally incorporate file add performance with dynamic previews and conclude the characteristic set with an asynchronous chat interface that simulates real-time interplay. Additionally, we be sure that the app runs seamlessly in Colab through the use of background threading and dynamic port allocation.
import sys
import subprocess
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "nicegui"], examine=True)
import threading, time, random, asyncio, base64, socket
from datetime import datetime
from nicegui import ui, occasions
class State:
def __init__(self):
self.todos = [
{"id": 1, "task": "Explore NiceGUI", "done": True, "priority": "High"},
{"id": 2, "task": "Build a dashboard", "done": False, "priority": "Medium"},
{"id": 3, "task": "Deploy to production", "done": False, "priority": "Low"},
]
self.next_id = 4
self.metrics = {"customers": 1247, "income": 8420, "orders": 53}
self.sequence = [random.uniform(20, 80) for _ in range(20)]
self.messages = [{"role": "assistant",
"text": "Hi! Type something and I will echo it back."}]
state = State()
def page_shell(energetic: str) -> None:
darkish = ui.dark_mode()
drawer = ui.left_drawer(worth=True).courses("bg-grey-2")
with drawer:
ui.label("Navigation").courses("text-lg font-bold p-2")
for label, path, icon in [
("Dashboard", "/", "dashboard"),
("Todos", "/todos", "check_circle"),
("Form", "/form", "edit_note"),
("Upload", "/upload", "upload_file"),
("Chat", "/chat", "chat"),
]:
cls = "w-full" + (" bg-primary text-white" if label == energetic else "")
ui.button(label,
on_click=lambda p=path: ui.navigate.to(p),
icon=icon).courses(cls).props("flat align=left no-caps")
with ui.header(elevated=True).courses("items-center justify-between bg-primary"):
with ui.row().courses("items-center"):
ui.button(on_click=drawer.toggle, icon="menu").props("flat coloration=white")
ui.label(" NiceGUI Tutorial").courses("text-xl font-semibold text-white")
ui.button(icon="dark_mode", on_click=darkish.toggle).props("flat coloration=white")
with ui.footer().courses("bg-grey-3 text-black justify-center"):
ui.label("Constructed with NiceGUI · Tutorial Demo")
We set up and import all required libraries, then initialize our software state. We outline a central State class to handle todos, metrics, chart knowledge, and chat messages throughout the app. We additionally constructed a reusable structure operate that gives navigation, a header, a footer, and darkish mode assist for all pages.
@ui.web page("/")
def dashboard():
page_shell("Dashboard")
with ui.column().courses("w-full p-6 gap-6"):
ui.label("Stay Dashboard").courses("text-3xl font-bold")
with ui.row().courses("gap-4 flex-wrap"):
for key, label, coloration, icon in [
("users", "Users", "primary", "group"),
("revenue", "Revenue", "positive", "attach_money"),
("orders", "Orders", "warning", "shopping_cart"),
]:
with ui.card().courses("w-60"):
with ui.row().courses("items-center justify-between w-full"):
ui.label(label).courses("text-gray-500")
ui.icon(icon, dimension="md").courses(f"text-{coloration}")
ui.label().courses(f"text-3xl font-bold text-{coloration}")
.bind_text_from(state.metrics, key, backward=lambda v: f"{v:,}")
with ui.card().courses("w-full"):
ui.label("Stay stream (updates each second)").courses("text-lg font-semibold")
chart = ui.echart({
"tooltip": {"set off": "axis"},
"xAxis": {"sort": "class", "knowledge": checklist(vary(len(state.sequence)))},
"yAxis": {"sort": "worth"},
"sequence": [{"data": list(state.series), "type": "line",
"smooth": True, "areaStyle": {}}],
}).courses("h-64 w-full")
def tick():
state.sequence.append(random.uniform(20, 80))
state.sequence.pop(0)
chart.choices["series"][0]["data"] = checklist(state.sequence)
chart.replace()
state.metrics["users"] += random.randint(-2, 4)
state.metrics["revenue"] += random.randint(-100, 200)
state.metrics["orders"] = max(0, state.metrics["orders"] + random.randint(-1, 3))
ui.timer(1.0, tick)
We create the dashboard web page and construction it with responsive UI parts. We bind metric playing cards on to the state to allow computerized updates and show real-time values. We additionally implement a dwell chart utilizing ECharts and dynamically replace each the chart and the metrics utilizing a timer.
@ui.web page("/todos")
def todos_page():
page_shell("Todos")
with ui.column().courses("w-full p-6 gap-4 max-w-4xl mx-auto"):
ui.label("Todos").courses("text-3xl font-bold")
with ui.card().courses("w-full"):
with ui.row().courses("w-full items-center gap-2"):
task_input = ui.enter(placeholder="What wants doing?").courses("flex-grow")
priority_sel = ui.choose(["Low", "Medium", "High"], worth="Medium").courses("w-36")
def add_todo():
if not task_input.worth or not task_input.worth.strip():
ui.notify("Activity can't be empty", sort="warning"); return
state.todos.append({
"id": state.next_id,
"process": task_input.worth.strip(),
"executed": False,
"precedence": priority_sel.worth,
})
state.next_id += 1
task_input.worth = ""
todo_list.refresh()
ui.notify("Added!", sort="optimistic")
ui.button("Add", icon="add", on_click=add_todo).props("coloration=major")
task_input.on("keydown.enter", add_todo)
@ui.refreshable
def todo_list():
if not state.todos:
ui.label("Nothing right here but ").courses("text-gray-500"); return
for todo in state.todos:
with ui.card().courses("w-full"):
with ui.row().courses("w-full items-center gap-3"):
ui.checkbox(worth=todo["done"],
on_change=lambda e, t=todo: t.replace(executed=e.worth))
lbl = ui.label(todo["task"]).courses("flex-grow text-lg")
if todo["done"]:
lbl.type("text-decoration: line-through; opacity: 0.5")
coloration = {"Excessive": "pink", "Medium": "orange", "Low": "inexperienced"}[todo["priority"]]
ui.badge(todo["priority"], coloration=coloration)
def make_del(t=todo):
def _del():
state.todos.take away(t)
todo_list.refresh()
ui.notify("Eliminated", sort="data")
return _del
ui.button(icon="delete", on_click=make_del())
.props("flat coloration=pink spherical dense")
todo_list()
We implement a whole CRUD-based todo system with add, replace, and delete performance. We deal with consumer enter validation and dynamically refresh the UI utilizing NiceGUI’s refreshable parts. We additionally improve the UI with checkboxes, badges, and notifications to enhance interactivity and suggestions.
@ui.web page("/kind")
def form_page():
page_shell("Type")
with ui.column().courses("w-full p-6 max-w-2xl mx-auto gap-4"):
ui.label("Profile Type").courses("text-3xl font-bold")
with ui.card().courses("w-full gap-2"):
title = ui.enter("Identify", validation={"Required": lambda v: bool(v)})
e-mail = ui.enter("Electronic mail", validation={"Have to be an e-mail": lambda v: "@" in (v or "")})
age = ui.quantity("Age", worth=18, min=0, max=120)
ui.label("Subscription plan").courses("mt-2 text-gray-600")
plan = ui.radio(["Free", "Pro", "Enterprise"], worth="Free").props("inline")
agree = ui.checkbox("I settle for the phrases")
async def submit():
if not (title.worth and "@" in (e-mail.worth or "") and agree.worth):
ui.notify("Please repair the shape first", sort="unfavorable"); return
with ui.dialog() as d, ui.card():
ui.label("Submitted!").courses("text-xl font-bold")
ui.label(f"Identify: {title.worth}")
ui.label(f"Electronic mail: {e-mail.worth}")
ui.label(f"Age: {age.worth}")
ui.label(f"Plan: {plan.worth}")
ui.button("OK", on_click=d.shut).props("coloration=major")
d.open()
ui.button("Submit", on_click=submit).props("coloration=major")
@ui.web page("/add")
def upload_page():
page_shell("Add")
with ui.column().courses("w-full p-6 max-w-3xl mx-auto gap-4"):
ui.label("File Add").courses("text-3xl font-bold")
end result = ui.column().courses("w-full")
def handle_upload(e: occasions.UploadEventArguments):
content material = e.content material.learn()
with end result:
with ui.card().courses("w-full"):
ui.label(f" {e.title}").courses("font-semibold")
ui.label(f"Dimension: {len(content material):,} bytes · sort: {e.sort}")
if e.sort and e.sort.startswith("picture/"):
b64 = base64.b64encode(content material).decode()
ui.picture(f"knowledge:{e.sort};base64,{b64}").courses("w-64 rounded")
else:
strive:
ui.code(content material[:500].decode("utf-8", errors="exchange"))
besides Exception:
go
ui.notify(f"Uploaded {e.title}", sort="optimistic")
ui.add(on_upload=handle_upload, a number of=True, auto_upload=True).courses("w-full")
We construct a kind with validation guidelines and deal with submission utilizing an asynchronous operate. We show consumer enter in a dialog upon profitable submission and guarantee correct validation earlier than processing. We additionally implement a file add characteristic that helps a number of information and offers picture previews and content material previews for different file varieties.
@ui.web page("/chat")
def chat_page():
page_shell("Chat")
with ui.column().courses("w-full p-6 max-w-3xl mx-auto gap-4"):
ui.label("Chat (echo bot)").courses("text-3xl font-bold")
@ui.refreshable
def chat_log():
for m in state.messages:
ui.chat_message(
m["text"],
title="You" if m["role"] == "consumer" else "Bot",
despatched=m["role"] == "consumer",
stamp=datetime.now().strftime("%H:%M"),
)
with ui.card().courses("w-full"):
chat_log()
async def ship():
textual content = (entry.worth or "").strip()
if not textual content:
return
state.messages.append({"position": "consumer", "textual content": textual content})
entry.worth = ""
chat_log.refresh()
await asyncio.sleep(1)
reply = f'You mentioned: "{textual content}" — that's {len(textual content)} characters!'
state.messages.append({"position": "assistant", "textual content": reply})
chat_log.refresh()
with ui.row().courses("w-full items-center"):
entry = ui.enter(placeholder="Kind a message…")
.courses("flex-grow").on("keydown.enter", ship)
ui.button(icon="ship", on_click=ship).props("coloration=major spherical")
def _free_port() -> int:
s = socket.socket()
s.bind(("", 0))
port = s.getsockname()[1]
s.shut()
return port
PORT = _free_port()
def _serve():
ui.run(host="0.0.0.0", port=PORT, reload=False, present=False,
title="NiceGUI Tutorial", storage_secret="colab-demo")
threading.Thread(goal=_serve, daemon=True).begin()
time.sleep(4)
strive:
from google.colab import output
from google.colab.output import eval_js
output.serve_kernel_port_as_iframe(PORT, top="850")
print(f"App operating on port {PORT}")
print("Open in a brand new browser tab:")
print(eval_js(f"google.colab.kernel.proxyPort({PORT})"))
besides ImportError:
print(f"Not in Colab — open http://localhost:{PORT} in your browser")
We develop an asynchronous chat interface that simulates real-time interplay. We handle chat messages within the shared state and dynamically refresh the chat log after every message. Additionally, we configure the app to run on a dynamically chosen free port in a background thread and expose it throughout the Colab setting.
In conclusion, we developed a complete understanding of find out how to construct and construction trendy net functions utilizing NiceGUI. We introduced collectively a number of superior ideas equivalent to state administration, reactive UI updates, routing, asynchronous workflows, and real-time visualization right into a single cohesive system. We additionally addressed sensible challenges, equivalent to operating net servers in pocket book environments and making certain part reusability. This end-to-end implementation demonstrates the pliability and energy of NiceGUI and in addition equips us with the abilities to prototype, take a look at, and scale interactive functions effectively.
Take a look at the Full Codes with Notebook here. Additionally, be at liberty to comply with us on Twitter and don’t neglect to hitch our 130k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Have to accomplice with us for selling your GitHub Repo OR Hugging Face Web page OR Product Launch OR Webinar and so on.? Connect with us
The put up Learn how to Construct a Totally Interactive Multi-Web page NiceGUI Software with Actual-Time Dashboard, CRUD Operations, File Add, and Async Chat appeared first on MarkTechPost.
