<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: williamabbott</title>
    <description>The latest articles on DEV Community by williamabbott (@williamabbott).</description>
    <link>https://dev.to/williamabbott</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F129904%2F6486f992-a5e3-4a87-90cc-d3fe4e21eb73.png</url>
      <title>DEV Community: williamabbott</title>
      <link>https://dev.to/williamabbott</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/williamabbott"/>
    <language>en</language>
    <item>
      <title>Introducing Django Cotton: Revolutionizing UI Composition in Django! 🚀</title>
      <dc:creator>williamabbott</dc:creator>
      <pubDate>Sun, 07 Jul 2024 14:12:51 +0000</pubDate>
      <link>https://dev.to/williamabbott/introducing-django-cotton-revolutionizing-ui-composition-in-django-2hg0</link>
      <guid>https://dev.to/williamabbott/introducing-django-cotton-revolutionizing-ui-composition-in-django-2hg0</guid>
      <description>&lt;h3&gt;
  
  
  Goodbye &lt;code&gt;{% extends, block, include, custom_tag %}&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Hello &lt;code&gt;&amp;lt;c-component /&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I’m excited to introduce Django Cotton, a game-changer for those who love Django but crave a more modern, component-based design for templates.&lt;/p&gt;

&lt;p&gt;Here’s why I built it and what it offers:&lt;/p&gt;

&lt;h3&gt;
  
  
  🌟 Key Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Modern UI Composition: Efficiently compose and reuse UI components.&lt;/li&gt;
&lt;li&gt;HTML-like Syntax: HTML-like tags for better editor support, semantic structure and expressive coding.&lt;/li&gt;
&lt;li&gt;Interoperable with Django: Enhances Django’s existing template system.&lt;/li&gt;
&lt;li&gt;Minimal Overhead: Compiles to native Django components with dynamic caching.&lt;/li&gt;
&lt;li&gt;Ideal for Tailwind Usage: Encapsulates content and style in one file.&lt;/li&gt;
&lt;li&gt;Complements HTMX: Reduces repetition and enhances maintainability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The problem with Django’s native tags
&lt;/h2&gt;

&lt;p&gt;Whilst you can build frontends with Django’s native tags, there are a few things that hold us back when we want to apply modern practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Django’s &lt;code&gt;{% block %}&lt;/code&gt; and &lt;code&gt;{% extends %}&lt;/code&gt; system strongly couples child and parent templates. This makes it hard to create a truly re-usable component that can be used in places without it having a related base template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What about &lt;code&gt;{% include %}&lt;/code&gt;? Modern libraries allow components to be highly configurable, whether it’s by attributes, passing variables, passing HTML with default and named slots. &lt;code&gt;{% include %}&lt;/code&gt; tags, whilst they have the ability to pass simple variables and text, they will not allow you to easily send HTML blocks with template expressions let alone other niceties such as boolean attributes, named slots etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can only get so far using &lt;code&gt;{% with %}&lt;/code&gt; tags. Whilst it allows us to provide variables and strings it quickly busies up your code and has the same limitations about passing more complex types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can custom templatetags help us? They get us so far in being able to create something like a re-usable component but managing things like variable scoping, nesting, slots, dynamic attributes can quickly increase complexity. You’re also still writing that verbose syntax that comes with Django templates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Your first component
&lt;/h2&gt;

&lt;p&gt;Cotton allows you to craft your interfaces using HTML-like tags.&lt;/p&gt;

&lt;p&gt;A component saved in &lt;code&gt;cotton/button.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- cotton/button.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-500 text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ slot }}
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can be used in a view or other component like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- in your view --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;c-button&amp;gt;&lt;/span&gt;Click!&lt;span class="nt"&gt;&amp;lt;/c-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is already covering the slot mechanism which simply outputs the content between the opening and closing tags. This means we’re already able to pass HTML to the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    Click!
&lt;span class="nt"&gt;&amp;lt;/c-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Named slots
&lt;/h2&gt;

&lt;p&gt;What if we wanted to position content in a predefined area and style within the component? Consider a ‘card’ component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- cotton/card.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border rounded p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border-b"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ title }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    {{ slot  }}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can target this content in a couple of ways, either as a title attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- in your view --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;c-card&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Furniture"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Hand made
&lt;span class="nt"&gt;&amp;lt;/c-card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or should the title contain HTML or require some Django template logic, then we can use a named slot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-card&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c-slot&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Really&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; awesome furniture

        {% if on_sale %}
                &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-red-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;SALE!&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        {% endif %}
    &lt;span class="nt"&gt;&amp;lt;/c-slot&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/c-card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Native tags inside attributes
&lt;/h2&gt;

&lt;p&gt;We are free to use &lt;code&gt;{{&lt;/code&gt; and &lt;code&gt;{%&lt;/code&gt; tags inside attributes like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- button.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ url }}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rounded p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ slot }}
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- in your view --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;c-button&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'product' product.id %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Product title
&lt;span class="nt"&gt;&amp;lt;/c-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Be more flexible with &lt;code&gt;{{ attrs }}&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;{{ attrs }}&lt;/code&gt; will provide a string of all key=”value” items specified on the component as attributes. This is useful for increasing versatility of your components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;attrs&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rounded p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ slot }}
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we change the implementation like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-button&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'product' product.id %}"&lt;/span&gt; 
    &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Product title
&lt;span class="nt"&gt;&amp;lt;/c-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the href and target attributes to the underlying element without having to specifically declare them in the component template.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example using HTMX
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-button&lt;/span&gt; 
    &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/product-list/?page=2"&lt;/span&gt;
    &lt;span class="na"&gt;hx-target=&lt;/span&gt;&lt;span class="s"&gt;"#replaceMe"&lt;/span&gt;
    &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Next page&lt;span class="nt"&gt;&amp;lt;/c-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are many more topics to cover, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;c-vars to define in-component variables to create default attributes&lt;/li&gt;
&lt;li&gt;Dynamic Attributes to pass python types and variables by reference&lt;/li&gt;
&lt;li&gt;Boolean Attributes to simplify boilerplate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more, checkout the docs site + repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://django-cotton.com" rel="noopener noreferrer"&gt;http://django-cotton.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/wrabit/django-cotton" rel="noopener noreferrer"&gt;https://github.com/wrabit/django-cotton&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I Built Cotton
&lt;/h3&gt;

&lt;p&gt;During ~20 years of building for the web, I’ve found that tools like Svelte, Vue.js, and Laravel’s blade components — with their expressive, semantic HTML-like syntax — coupled with utility-first styling tools like Tailwind CSS, provide an unbeatable combination for spinning up modular, reusable UIs. Recently, moving to Python and Django, I couldn’t find a similar package, so I built Cotton to fill that gap.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
