Skip to content

Creating Components

Components are the building blocks of your UI. Each component is a Python class paired with a Jinja2 template.

Basic Component

A component has two parts:

1. Python Class

from pyjinhx import BaseComponent


class Card(BaseComponent):
    id: str              # Required - unique identifier
    title: str           # Required field
    subtitle: str = ""   # Optional with default

2. HTML Template

PyJinHX uses Jinja2 templates for it's components:

<!-- card.html -->
<div id="{{ id }}" class="card">
    <h2>{{ title }}</h2>
    {% if subtitle %}
        <p class="subtitle">{{ subtitle }}</p>
    {% endif %}
</div>

You can use PascalCase components inside templates

You can even use PascalCase components as custom tags inside your component templates. This lets you compose components by nesting, like <Button .../> or <UserCard>...</UserCard>, directly within other templates. PyJinHx will automatically discover and render them as components.

The id Field

Every component requires an id:

button = Button(id="submit", text="Submit")  # OK
button = Button(text="Submit")  # Error: id is required

Customizing the id Field

You can override the id field in your component to automatically generate a value using Pydantic's default_factory. For example, to have a random UUID assigned if no id is passed:

import uuid
from pyjinhx import BaseComponent
from pydantic import Field

class MyComponent(BaseComponent):
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    # ... other fields ...

This way, when you instantiate MyComponent() without providing an id, a unique value will be generated.

Auto-generated IDs

When using Renderer with auto_id=True, IDs are generated automatically for template-side rendering.

Template Discovery

Templates are automatically discovered based on the class name:

Class Name Template File
Button button.html or button.jinja
ActionButton action_button.html, action-button.html, or .jinja variants
UserCard user_card.html, user-card.html, or .jinja variants

Template Location Requirement

Templates must be in the same directory as the Python class file.

Extra Fields

Normally, if you pass extra fields to a class that inherits from Pydantic's BaseModel, it will raise an error:

from pydantic import BaseModel
class Example(BaseModel):
    foo: int

Example(foo=1, bar=2)  # Raises ValidationError: extra fields not permitted

With BaseComponent, extra fields are accepted and available in the template context. This allows you to pass dictionaries or data objects with additional fields without raising validation errors.

from pyjinhx import BaseComponent

class Example(BaseComponent):
    foo: int

ex = Example(foo=1, bar=2)  # No error! 'bar' is just ignored