Django-components provides a seamless integration with HTML fragments with AJAX (HTML over the wire), whether you're using jQuery, HTMX, AlpineJS, vanilla JavaScript, or other.
If the fragment component has any JS or CSS, django-components will:
Info
What are HTML fragments and "HTML over the wire"?
It is one of the methods for updating the state in the browser UI upon user interaction.
How it works is that:
Components support different "strategies" for rendering JS and CSS.
Two of them are used to enable HTML fragments - "document" and "fragment".
What's the difference?
Document strategy¤Document strategy assumes that the rendered components will be embedded into the HTML of the initial page load. This means that:
<script>
and <style>
tags (see Default JS / CSS locations)A component is rendered as a "document" when:
{% component %}
Component.render()
or Component.render_to_response()
with the deps_strategy
kwarg set to "document"
(default)Example:
MyTable.render(
kwargs={...},
)
# or
MyTable.render(
kwargs={...},
deps_strategy="document",
)
Fragment strategy¤
Fragment strategy assumes that the main HTML has already been rendered and loaded on the page. The component renders HTML that will be inserted into the page as a fragment, at a LATER time:
{% component_js_dependencies %}
inside of fragments are ignored.<script>
to trigger a call to its asset manager JS script, which will load the JS and CSS smartly.A component is rendered as "fragment" when:
Component.render()
or Component.render_to_response()
with the deps_strategy
kwarg set to "fragment"
Example:
MyTable.render(
kwargs={...},
deps_strategy="fragment",
)
Live examples¤
For live interactive examples, start our demo project (sampleproject
).
Then navigate to these URLs:
/fragment/base/alpine
/fragment/base/htmx
/fragment/base/js
This is the HTML into which a fragment will be loaded using HTMX.
[root]/components/demo.pyfrom django_components import Component, types
class MyPage(Component):
template = """
{% load component_tags %}
<!DOCTYPE html>
<html>
<head>
{% component_css_dependencies %}
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
</head>
<body>
<div id="target">OLD</div>
<button
hx-get="/mypage/frag"
hx-swap="outerHTML"
hx-target="#target"
>
Click me!
</button>
{% component_js_dependencies %}
</body>
</html>
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(request=request)
2. Define fragment HTML¤
The fragment to be inserted into the document.
IMPORTANT: Don't forget to set deps_strategy="fragment"
class Frag(Component):
template = """
<div class="frag">
123
<span id="frag-text"></span>
</div>
"""
js = """
document.querySelector('#frag-text').textContent = 'xxx';
"""
css = """
.frag {
background: blue;
}
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(
request=request,
# IMPORTANT: Don't forget `deps_strategy="fragment"`
deps_strategy="fragment",
)
3. Create view and URLs¤ [app]/urls.py
from django.urls import path
from components.demo import MyPage, Frag
urlpatterns = [
path("mypage/", MyPage.as_view())
path("mypage/frag", Frag.as_view()),
]
Example - AlpineJS¤ 1. Define document HTML¤
This is the HTML into which a fragment will be loaded using AlpineJS.
[root]/components/demo.pyfrom django_components import Component, types
class MyPage(Component):
template = """
{% load component_tags %}
<!DOCTYPE html>
<html>
<head>
{% component_css_dependencies %}
<script defer src="https://unpkg.com/alpinejs"></script>
</head>
<body x-data="{
htmlVar: 'OLD',
loadFragment: function () {
const url = '/mypage/frag';
fetch(url)
.then(response => response.text())
.then(html => {
this.htmlVar = html;
});
}
}">
<div id="target" x-html="htmlVar">OLD</div>
<button @click="loadFragment">
Click me!
</button>
{% component_js_dependencies %}
</body>
</html>
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(request=request)
2. Define fragment HTML¤
The fragment to be inserted into the document.
IMPORTANT: Don't forget to set deps_strategy="fragment"
class Frag(Component):
# NOTE: We wrap the actual fragment in a template tag with x-if="false" to prevent it
# from being rendered until we have registered the component with AlpineJS.
template = """
<template x-if="false" data-name="frag">
<div class="frag">
123
<span x-data="frag" x-text="fragVal">
</span>
</div>
</template>
"""
js = """
Alpine.data('frag', () => ({
fragVal: 'xxx',
}));
// Now that the component has been defined in AlpineJS, we can "activate"
// all instances where we use the `x-data="frag"` directive.
document.querySelectorAll('[data-name="frag"]').forEach((el) => {
el.setAttribute('x-if', 'true');
});
"""
css = """
.frag {
background: blue;
}
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(
request=request,
# IMPORTANT: Don't forget `deps_strategy="fragment"`
deps_strategy="fragment",
)
3. Create view and URLs¤ [app]/urls.py
from django.urls import path
from components.demo import MyPage, Frag
urlpatterns = [
path("mypage/", MyPage.as_view())
path("mypage/frag", Frag.as_view()),
]
Example - Vanilla JS¤ 1. Define document HTML¤
This is the HTML into which a fragment will be loaded using vanilla JS.
[root]/components/demo.pyfrom django_components import Component, types
class MyPage(Component):
template = """
{% load component_tags %}
<!DOCTYPE html>
<html>
<head>
{% component_css_dependencies %}
</head>
<body>
<div id="target">OLD</div>
<button>
Click me!
</button>
<script>
const url = `/mypage/frag`;
document.querySelector('#loader').addEventListener('click', function () {
fetch(url)
.then(response => response.text())
.then(html => {
document.querySelector('#target').outerHTML = html;
});
});
</script>
{% component_js_dependencies %}
</body>
</html>
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(request=request)
2. Define fragment HTML¤
The fragment to be inserted into the document.
IMPORTANT: Don't forget to set deps_strategy="fragment"
class Frag(Component):
template = """
<div class="frag">
123
<span id="frag-text"></span>
</div>
"""
js = """
document.querySelector('#frag-text').textContent = 'xxx';
"""
css = """
.frag {
background: blue;
}
"""
class View:
def get(self, request):
return self.component_cls.render_to_response(
request=request,
# IMPORTANT: Don't forget `deps_strategy="fragment"`
deps_strategy="fragment",
)
3. Create view and URLs¤ [app]/urls.py
from django.urls import path
from components.demo import MyPage, Frag
urlpatterns = [
path("mypage/", MyPage.as_view())
path("mypage/frag", Frag.as_view()),
]
2025-05-25 Juro Oravec
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4