Components in templates
By the end of this section, we want to be able to use our components in Django templates like so:
{% load component_tags %}
<!DOCTYPE html>
<html>
<head>
<title>My example calendar</title>
</head>
<body>
{% component "calendar" / %}
</body>
<html>
1. Register component¤
First, however, we need to register our component class with ComponentRegistry
.
To register a component with a ComponentRegistry
, we will use the @register
decorator, and give it a name under which the component will be accessible from within the template:
from django_components import Component, register # <--- new
@register("calendar") # <--- new
class Calendar(Component):
template_name = "calendar.html"
class Media:
js = "calendar.js"
css = "calendar.css"
def get_context_data(self):
return {
"date": "1970-01-01",
}
This will register the component to the default registry. Default registry is loaded into the template by calling {% load component_tags %}
inside the template.
Info
Why do we have to register components?
We want to use our component as a template tag ({% ... %}
) in Django template.
In Django, template tags are managed by the Library
instances. Whenever you include {% load xxx %}
in your template, you are loading a Library
instance into your template.
ComponentRegistry
acts like a router and connects the registered components with the associated Library
.
That way, when you include {% load component_tags %}
in your template, you are able to "call" components like {% component "calendar" / %}
.
ComponentRegistries
also make it possible to group and share components as standalone packages. Learn more here.
Note
You can create custom ComponentRegistry
instances, which will use different Library
instances. In that case you will have to load different libraries depending on which components you want to use:
Example 1 - Using component defined in the default registry
Example 2 - Using component defined in a custom registry
Note that, because the tag name component
is use by the default ComponentRegistry, the custom registry was configured to use the tag my_component
instead. Read more here
2. Load and use the component in template¤
The component is now registered under the name calendar
. All that remains to do is to load and render the component inside a template:
{% load component_tags %} {# Load the default registry #}
<!DOCTYPE html>
<html>
<head>
<title>My example calendar</title>
</head>
<body>
{% component "calendar" / %} {# Render the component #}
</body>
<html>
Info
Component tags should end with /
if they do not contain any Slot fills. But you can also use {% endcomponent %}
instead:
We defined the Calendar's template as
and the variable date
as "1970-01-01"
.
Thus, the final output will look something like this:
<!DOCTYPE html>
<html>
<head>
<title>My example calendar</title>
<style>
.calendar {
width: 200px;
background: pink;
}
.calendar span {
font-weight: bold;
}
</style>
</head>
<body>
<div class="calendar">
Today's date is <span>1970-01-01</span>
</div>
<script>
(function () {
document.querySelector(".calendar").onclick = () => {
alert("Clicked calendar!");
};
})();
</script>
</body>
<html>
This makes it possible to organize your front-end around reusable components, instead of relying on template tags and keeping your CSS and Javascript in the static directory.
Info
Remember that you can use {% component_js_dependencies %}
and {% component_css_dependencies %}
to change where the <script>
and <style>
tags will be rendered (See JS and CSS output locations).
Info
How does django-components pick up registered components?
Notice that it was enough to add @register
to the component. We didn't need to import the component file anywhere to execute it.
This is because django-components automatically imports all Python files found in the component directories during an event called Autodiscovery.
So with Autodiscovery, it's the same as if you manually imported the component files on the ready()
hook:
You can now render the components! But our component will render the same content now matter where and how many times we use it. Let's parametrise some of its state, so that our Calendar component is configurable from within the template ➡️