==========
Components
==========
Components are a subclass of `Stream` that simplifies implementation of streams.
Creating a Component
====================
Components are a type of stream with a template. As components are a type of stream, components must be either be created in or imported to `streams.py` to be registered.
Quick example
-------------
.. code-block:: python
:caption: app/streams.py
from turbo.components import BroadcastComponent
class AlertBroadcastComponent(BroadcastComponent):
template_name = "components/sample_broadcast_component.html"
Add a simple template:
.. code-block:: html
:caption: templates/components/sample_broadcast_component.html
{% if alert_content %}
{{alert_content}}
{% endif %}
The component can be rendered in one of two ways.
.. code-block:: html
:caption: templates/view_template.html
{% load turbo_streams %}
If an instance of the component is passed in via the view:
{% turbo_component alert_component %}
To access the component globally:
{% turbo_component "app_name:AlertBroadcastComponent" %}
This will insert the contents of `components/sample_broadcast_component.html` on the template.
To stream updated content to the view, open a python terminal, instanciate the component, and render a new update.
.. code-block:: python
from app_name.streams import AlertBroadcastComponent
alert_component = AlertBroadcastComponent()
alert_component.render(
alert_class='warning',
alert_content='The server will restart in 10 minutes'
)
.. admonition:: Multiple identical components
Using the same component twice in a template, will only update the first component on the page. This is a current purposeful limitation of the Hotwire framework. In the above examples, while the components will render initially, only the first component will receive the streamed content.
Full example
------------
.. code-block:: python
:caption: app/streams.py
from turbo.components import BroadcastComponent
class AlertBroadcastComponent(BroadcastComponent):
template_name = "components/sample_broadcast_component.html"
def get_context(self):
"""
Return the default context to render a component.
"""
return {}
def user_passes_test(self, user):
"""
Only allow access to the component stream if the user passes
this test.
"""
return user.is_authenticated
.. module:: turbo.components
BroadcastComponent
==================
.. class:: BroadcastComponent
A broadcast component will stream a template to all users.
Example
-------
.. code-block:: python
:caption: app/streams.py
from turbo.components import BroadcastComponent
class AlertBroadcastComponent(BroadcastComponent):
template_name = "components/sample_broadcast_component.html"
.. code-block:: html
:caption: templates/components/sample_broadcast_component.html
{% if alert_content %}
{{alert_content}}
{% endif %}
.. code-block:: html
:caption: templates/view_template.html
{% load turbo_streams %}
{% turbo_component "app_name:AlertBroadcastComponent" %}
To stream an updated template to the component:
.. code-block:: python
from .streams import AlertBroadcastComponent
component = AlertBroadcastComponent()
component.render(
alert_class='warning',
alert_content='The server will restart in 10 minutes'
)
UserBroadcastComponent
======================
.. class:: UserBroadcastComponent
A user broadcast component will stream a template to a specific user.
Example
-------
.. code-block:: python
:caption: app/streams.py
from turbo.components import UserBroadcastComponent
class CartCountComponent(UserBroadcastComponent):
template_name = "components/cart_count_component.html"
def get_context(self):
return {
"count": self.user.cart.items_in_cart
}
.. code-block:: html
:caption: templates/components/cart_count_component.html
.. code-block:: html
:caption: templates/view_template.html
{% load turbo_streams %}
{% turbo_component "chat:CartCountComponent" request.user %}
or
{% turbo_component cart_count_component %}