Skip to content

Component defaults

When a component is being rendered, the component inputs are passed to various methods like get_template_data(), get_js_data(), or get_css_data().

It can be cumbersome to specify default values for each input in each method.

To make things easier, Components can specify their defaults. Defaults are used when no value is provided, or when the value is set to None for a particular input.

Defining defaultsยค

To define defaults for a component, you create a nested Defaults class within your Component class. Each attribute in the Defaults class represents a default value for a corresponding input.

from django_components import Component, Default, register

@register("my_table")
class MyTable(Component):

    class Defaults:
        position = "left"
        selected_items = Default(lambda: [1, 2, 3])

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "position": kwargs["position"],
            "selected_items": kwargs["selected_items"],
        }

    ...

In this example, position is a simple default value, while selected_items uses a factory function wrapped in Default to ensure a new list is created each time the default is used.

Now, when we render the component, the defaults will be applied:

{% component "my_table" position="right" / %}

In this case:

  • position input is set to right, so no defaults applied
  • selected_items is not set, so it will be set to [1, 2, 3].

Same applies to rendering the Component in Python with the render() method:

MyTable.render(
    kwargs={
        "position": "right",
        "selected_items": None,
    },
)

Notice that we've set selected_items to None. None values are treated as missing values, and so selected_items will be set to [1, 2, 3].

Warning

The defaults are aplied only to keyword arguments. They are NOT applied to positional arguments!

Defaults from Kwargsยค

If you are using Component.Kwargs to specify the component input, you can set the defaults directly on Kwargs:

class ProfileCard(Component):
    class Kwargs:
        user_id: int
        show_details: bool = True

Which is the same as:

class ProfileCard(Component):
    class Kwargs:
        user_id: int
        show_details: bool

    class Defaults:
        show_details = True

Warning

This works only when Component.Kwargs is a plain class, NamedTuple or dataclass.

Default factoriesยค

For objects such as lists, dictionaries or other instances, you have to be careful - if you simply set a default value, this instance will be shared across all instances of the component!

from django_components import Component

class MyTable(Component):
    class Defaults:
        # All instances will share the same list!
        selected_items = [1, 2, 3]

To avoid this, you can use a factory function wrapped in Default.

from django_components import Component, Default

class MyTable(Component):
    class Defaults:
        # A new list is created for each instance
        selected_items = Default(lambda: [1, 2, 3])

This is similar to how the dataclass fields work.

In fact, you can also use the dataclass's field function to define the factories:

from dataclasses import field
from django_components import Component

class MyTable(Component):
    class Defaults:
        selected_items = field(default_factory=lambda: [1, 2, 3])

Accessing defaultsยค

The defaults may be defined on both Component.Defaults and Component.Kwargs classes.

To get a final, merged dictionary of all the component's defaults, use get_component_defaults():

from django_components import Component, Default, get_component_defaults

class MyTable(Component):
    class Kwargs:
        position: str
        order: int
        items: list[int]
        variable: str = "from_kwargs"

    class Defaults:
        position: str = "left"
        items = Default(lambda: [1, 2, 3])

defaults = get_component_defaults(MyTable)
# {
#     "position": "left",
#     "items": [1, 2, 3],
#     "variable": "from_kwargs",
# }