Lawrence  Lesch

Lawrence Lesch

1659807720

Htmx: </> Htmx - High Power tools for HTML

</> Htmx

high power tools for HTML

introduction

htmx allows you to access AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext

htmx is small (~10k min.gz'd), dependency-free, extendable & IE11 compatible

motivation

  • Why should only <a> and <form> be able to make HTTP requests?
  • Why should only click & submit events trigger them?
  • Why should only GET & POST be available?
  • Why should you only be able to replace the entire screen?

By removing these arbitrary constraints htmx completes HTML as a hypertext

quick start

  <script src="https://unpkg.com/htmx.org@1.8.0"></script>
  <!-- have a button POST a click via AJAX -->
  <button hx-post="/clicked" hx-swap="outerHTML">
    Click Me
  </button>

The hx-post and hx-swap attributes tell htmx:

"When a user clicks on this button, issue an AJAX request to /clicked, and replace the entire button with the response"

htmx is the successor to intercooler.js

installing as a node package

To install using npm:

npm install htmx.org --save

Note there is an old broken package called htmx. This is htmx.org.

website & docs

contributing

  • please write code, including tests, in ES5 for IE 11 compatibility
  • please include test cases in /test and docs in /www
  • if you are adding a feature, consider doing it as an extension instead to keep the core htmx code tidy
  • development pull requests should be against the dev branch, docs fixes can be made directly against master
  • No time? Then become a sponsor

hacking guide

To develop htmx locally, you will need to install the development dependencies. Use node 15 and run:

npm install

Then, run a web server in the root. This is easiest with Python:

python3 -m http.server

You can then run the test suite by navigating to:

http://0.0.0.0:8000/test/

At this point you can modify /src/htmx.js to add features, and then add tests in the appropriate area under /test.

  • /test/index.html - the root test page from which all other tests are included
  • /test/attributes - attribute specific tests
  • /test/core - core functionality tests
  • /test/core/regressions.js - regression tests
  • /test/ext - extension tests
  • /test/manual - manual tests that cannot be automated

htmx uses the mocha testing framework, the chai assertion framework and sinon to mock out AJAX requests. They are all OK.

haiku

javascript fatigue:
longing for a hypertext
already in hand

Author: Bigskysoftware
Source Code: https://github.com/bigskysoftware/htmx 
License: BSD-2-Clause license

#javascript #html #htmx 

Htmx: </> Htmx - High Power tools for HTML
伊藤  直子

伊藤 直子

1659360546

HTMX: JavaScript を使用しない Web アプリの最新のアプローチ

ドキュメントによると、HTMXライブラリを使用すると、Javascript を使用せずに最新のブラウザー機能を追加できます。CSS TransitionsAJAXWebSockets、およびServer-Sent Eventsに HTML で直接アクセスし、属性を使用して最新のユーザー インターフェイスをすばやく構築できます。JavaScript を使用せずにクライアント側で Web アプリを開発することは可能でしょうか? このチュートリアルでは、HTMX の驚異的な機能をすべて調べます。JavaScript コードを記述せずに、Ajax リクエストの送信、ファイルのアップロード、入力の検証、CSS トランジションのトリガーの方法を学習します。

HTMX とは何ですか? なぜ重要なのですか?

2013 年、Carson Gross は代替のフロントエンド ライブラリintercooler.jsを作成しました。このライブラリには、フロントエンド Web 開発の複雑さを簡素化するためのキャッチフレーズ「Ajax With Attributes」が含まれています。新しいバージョンの intercooler.js がバージョン 2.0 になり、HTML 内で直接 Ajax、WebSockets、CSS トランジション、および Server-Sent Events にアクセスできるようにするライブラリとして記述されたhtmxになりました。

HTMX の作成者は、Web の元のモデルを使用して Web アプリを作成することにより、HTML の力を活用しようとしていると述べています。このアプローチでは、開発者は同様の機能を実現するために JavaScript を記述する必要はありません。代わりに、追加の HTML 属性を使用して、動的なコンテンツと更新を実現します。Gross 氏によると、これらが htmx の背後にある動機です。

  • なぜ HTTP リクエストのみを作成できる必要<a><form>あるのですか?
  • click&submitイベントだけがそれらをトリガーするのはなぜですか?
  • GET&POSTメソッドのみを使用できる必要があるのはなぜですか?
  • entireなぜスクリーンだけ交換できるのですか?

「恣意的な制約を取り除くことで、htmx は HTML をハイパーテキストとして完成させます」と彼は結論付けています。

HTMX を使用すると、開発者はプログレス バー遅延読み込み無限スクロールインライン検証など、最小限の HTML とスタイリングでいくつかの UI 機能と UX パターンを実装できます

HTMX アプローチは、Vue.js や React などの他のフロントエンド フレームワークとは異なります。クライアント側アプリケーションは JavaScript を使用してサーバーから情報を要求し、JSON 形式で受信します。HTMX では、サーバーにリクエストを送信すると、エンドポイントは完全な形式の Html を返し、ページの一部を更新します。アプリケーション ロジックはバックエンドで発生するため、HTMX を任意のサーバー側テクノロジと統合できます。

HTMX の設定

HTMX をセットアップするには、CDN 経由で読み込んで、以下のように head タグに追加します。

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

もう 1 つの方法は、htmx.min.js ソース ファイルをダウンロードしてプロジェクトの適切なディレクトリに追加し、次のようなスクリプト タグを使用して必要な場所に挿入することです。

<script src="/path/to/htmx.min.js"></script>

npm以下のようにしてHTMX をインストールすることもできます。

npm install htmx.org

HTMX を使用して Ajax リクエストを送信する

HTMX は、HTML から直接 AJAX リクエストを作成できるようにする一連の属性を提供します。

  • hx-post- 指定された URL に POST 要求を発行します。
  • hx-get- 指定された URL に GET リクエストを発行します。
  • hx-put- 指定された URL に PUT 要求を発行します。
  • hx-patch- 指定された URL に PATCH リクエストを発行します。
  • hx-delete- 指定された URL に DELETE リクエストを発行します。

上記の各属性は、AJAX 要求を送信する URL を受け入れます。そのため、要素がトリガーされるたびに、指定されたタイプのリクエストが指定された URL に送信されます。以下の例を考えてみましょう。

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

上記のデモでは、ユーザーがLoad Jokes要素をクリックしたときにGETリクエスト ( hx-get) をジョーク API エンドポイント URL ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode ) に送信し、 div 要素への応答。ここでは、均一で整形式のジョークを提供する REST API であるデモJoke APIを使用しました。

Htmx-デモ

コードペン リンク

次に、応答を別の HTML 要素にロードする方法を調べます。

HTMX によるリクエストのトリガー

要素の「自然な」イベントは、デフォルトで Ajax リクエストを自動的に開始します。たとえば、onchangeイベント トリガーtextareainput、およびselectonsubmitイベントがトリガーされている間form。イベントは、他のclickすべての要求をトリガーします。リクエストをトリガーするイベントを指定する必要がある場合、HTMX は独自の「hx-trigger」を提供します。

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

トリガー リクエスト

コードペンリンク

上記のコードの div 要素の上にマウスを置くと、提供された URL エンドポイントに GET 要求が送信され、Jokes が取得されます。

HTMX による修飾子のトリガー

前のセクションで説明したように、hx-trigger属性を変更してその動作を変更することができます。たとえば、リクエストを 1 回だけ発生させたい場合はonce、トリガーに修飾子を使用できます。

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

以下は、利用可能な修飾子のリストです。

changed- 要素の値が変更された場合にリクエストを送信します。

display:<time interval>delay-1s-要求を送信する前に、一定時間 (例: ) 待機します。

throttle: <time interval>delay-1s-要求を送信する前に、指定された時間 (例: ) 待機します。delayとは異なり、制限時間に達する前に新しいイベントが発生した場合、イベントは破棄されます。つまり、時間の終わりにリクエストがトリガーされます。

form: <css selector>- 別の要素のイベントをリッスンします。これは、キーボード ショートカットなどに使用できます。

上記のすべての属性を使用して、Active Search Box パターンなどの一般的な UX パターンを実装できます。この例では、上記の属性の動作を確認できます。

属性によるポーリングhtmx-trigger

HTMX トリガー属性を使用して、要素がnイベントの発生を待つ代わりに、指定された URL を毎秒ポーリングするように指定することもできます。

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

ここで、HTMX はブラウザに GET リクエストを/V2.jokeapi3 秒ごとに URL に送信し、レスポンスを div 要素に表示するように指示します。

HTMX によるポーリング

コードペンリンク

リクエストインジケーター

ブラウザーはフィードバックを提供しないため、何かが起こっていることをユーザーに通知すると便利です。「htmx-indicator」クラスを使用して、HTMX でこれを行うことができます。

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

「htmx-indicator」クラスは、このクラスを持つ要素の不透明度を0デフォルトで に設定し、非表示にしますが、DOM に存在します。「ジョークの読み込み」ボタンをクリックすると、ローダー インジケーターを表示する「htmx-request」クラスが追加されます。

リクエストインジケーター

コードペンリンク

ターゲティング要素

前述のように、HTMX は AJAX 要求への応答を要求を開始した要素に読み込みます。「hx-target」属性を使用すると、リクエストを開始した要素とは異なる要素にレスポンスをロードできます。「hx-target」は CSS セレクターを受け入れ、AJAX 応答をターゲット要素に自動的にロードします。

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

上記のデモでは、ボタンをクリックすると、その下の要素load jokesに応答が自動的に読み込まれます。div

htmx_target

コードペンリンク

スワッピング

前のセクションのようhx-targetに、HTMX は Dom 内で Ajax によって返された応答をロードする方法を決定する別の方法を提供します。これを行うには、「hx-swap」属性を以下にリストされている値のいずれかで設定します。

  • innerHTML: これはデフォルト値です。リクエストを送信するターゲット要素にコンテンツを挿入します。outerHTML: ターゲット要素全体を返されたコンテンツに置き換えます。
  • afterbegin: ターゲット要素内の最初の子の前にレスポンスを追加します。
  • beforebegin: リクエストをトリガーする実際の要素の親要素としてレスポンスを先頭に追加します。
  • beforeend: リクエストを送信した要素の最後の子の後にレスポンスを追加します。
  • afterend: と同様にbeforeend、リクエストを送信する要素の後にレスポンスを追加します。
  • none: このオプションは、AJAX 要求からの応答を追加または先頭に追加しません。

上記の属性の一部を使用したスクロール プログレス バーの例を次に示します ( https://htmx.org/examples/progress-bar )。

HTMX との同期リクエスト

場合によっては、2 つの要素間で要求を同期する必要があります。ある要素からのリクエストで別の要素のリクエストをオーバーライドしたい、または他の要素のリクエストが完了するまで待機したいとします。hx-sync属性を使用してこれを行うことができます。以下のコードを検討してください。

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

上記の例では、フォームの送信と個別のinput検証リクエストがあります。を使用しないhx-syncと、フォームに入力して送信すると、 と への 2 つの並列リクエストが同時にトリガー/change/validateれます。ドキュメントによると、入力で使用hx-sync=" closest form:abort" すると、フォーム リクエストが存在する場合、または入力リクエストの実行中に開始された場合は、入力リクエストを監視しform、入力リクエストを停止します。

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

このアプローチを使用すると、2 つの要素間の同期の問題を宣言的に修正できます。hx-sync属性の詳細については、こちらをご覧ください。

HTMX を使用したファイルのアップロード

HTMX を使用すると、処理のために Ajax 経由でバックエンドに送信されるファイル アップロード フォームを作成できます。動画、画像、ドキュメントなどのファイルを簡単に送信できます。リクエストを送信する親要素にhx-encoding値を持つ属性を直接埋め込むことで、HTMX でこれを実装できます。multipart/form-data

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

HTMX による入力検証

htmx は HTML 5 Validation API をネイティブに組み込んでいるため、検証可能な入力が無効な場合、リクエストは送信されません。この機能は、AJAX 要求と WebSockets 送信の両方に適用されます。また、HTMX は、カスタム検証とエラー処理をフックするために使用できる検証に関するイベントを発生させます。現在、次のイベントを利用できます。

  • `htmx:validation: validate – カスタム検証ロジックを追加するために使用されます。
  • htmx:validation:failed` – このイベントは、要素の検証が false を返したときに発生します。たとえば、無効な入力を示します。
  • htmx:validation: halted: 検証エラーのためにリクエストが発行されなかった場合に、このイベントが呼び出されます。オブジェクト内の特定のエラーを見つけることができevent.detail.errorsます。

入力がhyperscriptを使用しhtmx:validate:validateて値を持つことを保証するために、イベントを使用する入力を考えます。David

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

常にバイパスできるため、すべてのクライアント側の検証はサーバー上で行う必要があることに注意することが重要です。

HTMX を使用した CSS アニメーション

Htmx を使用すると、CSS トランジションを使用して、JavaScript を使用せずに CSS と HTML のみを使用して、スムーズなアニメーションとトランジションを Web ページに追加できます。HTMX は と呼ばれる強力なアニメーション拡張機能を提供します。これにより、 or属性class-toolsを使用して要素にスワップする、または要素からスワップする CSS クラスを定義できます。classesdata-classes

classes要素に属性を割り当てることで拡張機能を使用できます。classes属性値は、& 文字で区切られた「ラン」で構成されます。実行では、指定された遅延でクラス操作を順番に適用します。これらのクラス操作にはaddremove、 、またはtoggleCSS クラス名が付き、オプションでコロン: と時間遅延が付きます。

<div classes= “add sample-demo: 1s”></div>

sample-demoブラウザーのコンテンツが読み込まれると、HTMX は1 秒後に div に新しいクラスを自動的に追加します。以下のデモ例を見てみましょう。

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transition

CodePen-Link HTMXを使用して魅力的なアニメーションとトランジションを行う方法の詳細については、こちらを参照してください。

HTMX はさまざまなサーバー側フレームワークとシームレスに統合されますが、一部のフレームワークには HTMX をインストールするための代替手段がある場合があります。このリンクをチェックして、HTMX をさまざまなサーバー側フレームワークと統合する方法を調べてください。

結論

HTMX は信じられないほどのテクノロジであり、私はそれに興奮しており、次のプロジェクトの本番環境で使用するのが待ちきれません. このチュートリアルでは、HTMX をインストールする方法、Ajax リクエストを送信する方法、ファイルをアップロードする方法、入力を検証する方法、クライアント側で JavaScript を使用せずに CSS トランジションを作成する方法について説明しました。

このリンクをチェックして、編集してプロジェクトに統合できる HTMX で実装されたUX パターンのデモのセットを確認してください。

次のリンク ( https://htmx.org/examples/ ) には、編集してプロジェクトに統合できるUX パターンデモのセットが含まれています。

ソース: https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

HTMX: JavaScript を使用しない Web アプリの最新のアプローチ
Anne  de Morel

Anne de Morel

1659358800

HTMX : La Nouvelle Approche Pour Les Applications Web Sans JavaScript

Selon la documentation, la bibliothèque HTMX vous permet d'ajouter des fonctionnalités de navigateur modernes sans utiliser Javascript. Il vous donne accès aux transitions CSS , AJAX , WebSockets et événements envoyés par le serveur directement en HTML, en utilisant des attributs pour créer rapidement des interfaces utilisateur modernes. Serait-il possible de développer des applications Web côté client sans JavaScript ? Dans ce didacticiel, nous allons explorer toutes les fonctionnalités époustouflantes de HTMX. Vous apprendrez à envoyer des requêtes Ajax, à télécharger des fichiers, à valider des entrées et à déclencher des transitions CSS sans écrire de code JavaScript.

Qu'est-ce que HTMX et pourquoi est-ce important ?

En 2013, Carson Gross a créé une bibliothèque frontale alternative intercooler.js , avec le slogan "Ajax With Attributes" pour simplifier la complexité du développement Web frontal. Une nouvelle version d'intercooler.js a atteint la version 2.0 et est devenue htmx décrit comme une bibliothèque qui vous permet d'accéder à Ajax, WebSockets, la transition CSS et les événements envoyés par le serveur directement dans HTML.

Le créateur de HTMX dit qu'il tente de tirer parti de la puissance de HTML en utilisant le modèle original du Web pour créer des applications Web. Avec cette approche, les développeurs n'ont pas besoin d'écrire du JavaScript pour obtenir des fonctionnalités similaires. Au lieu de cela, ils utilisent des attributs HTML supplémentaires pour obtenir un contenu et des mises à jour dynamiques. Selon Gross, ce sont les motivations derrière htmx :

  • Pourquoi ne devrait-on <a>et ne <form>peut-on que faire des requêtes HTTP ?
  • Pourquoi seuls les événements click& devraient-ils submitles déclencher ?
  • Pourquoi seules les méthodes GET& devraient-elles être disponibles ?POST
  • Pourquoi ne devriez-vous pouvoir remplacer que l' entireécran ?

« En supprimant les contraintes arbitraires, htmx complète le HTML en tant qu'hypertexte », conclut-il.

Avec HTMX, les développeurs peuvent implémenter plusieurs fonctionnalités d'interface utilisateur et modèles UX avec un minimum de code HTML et de style, tels que la barre de progression , le chargement différé , le défilement infini , la validation en ligne , etc.

L'approche HTMX diffère des autres frameworks frontaux tels que Vue.js et React, où l'application côté client utilise JavaScript pour demander des informations au serveur et les recevoir au format JSON. Avec HTMX, lorsque vous faites une demande au serveur, le point de terminaison renverra Html entièrement formé et mettra à jour une partie de la page. Vous pouvez intégrer HTMX à n'importe quelle technologie côté serveur puisque la logique d'application se produit sur le backend.

Configurer HTMX

Pour configurer HTMX, vous pouvez apparemment le charger via un CDN et l'ajouter à votre balise principale comme ceci ci-dessous :

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

Une autre méthode consiste à télécharger le fichier source htmx.min.js et à l'ajouter dans le répertoire approprié de votre projet, puis à l'insérer si nécessaire avec une balise de script comme celle-ci :

<script src="/path/to/htmx.min.js"></script>

Vous pouvez également installer HTMX via npmcomme ceci ci-dessous :

npm install htmx.org

Envoi de requêtes Ajax à l'aide de HTML

HTMX propose un ensemble d'attributs qui vous permettent de faire des requêtes AJAX directement à partir de HTML.

  • hx-post- envoie une requête POST à ​​l'URL donnée.
  • hx-get- envoie une requête GET à l'URL donnée.
  • hx-put- envoie une requête PUT à l'URL donnée.
  • hx-patch- envoie une requête PATCH à l'URL donnée.
  • hx-delete- envoie une requête DELETE à l'URL donnée.

Chacun de ces attributs ci-dessus accepte une URL à laquelle envoyer une requête AJAX. Ainsi, chaque fois que l'élément est déclenché, il envoie le type de requête spécifié à l'URL donnée. Considérez l'exemple ci-dessous :

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

La démo ci-dessus indique au navigateur que lorsqu'un utilisateur clique sur l' Load Jokesélément, il doit envoyer une GETrequête ( hx-get) à l'URL du point de terminaison jokeapi ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode ) et charger le réponse dans l'élément div. Nous avons utilisé ici une API Joke de démonstration , une API REST qui sert des blagues uniformément et bien formatées.

Démo Htmx

Lien Codepen

Ensuite, nous examinerons comment charger la réponse dans un autre élément HTML.

Déclencher des requêtes avec HTMX

L'événement "naturel" d'un élément lance automatiquement les requêtes Ajax par défaut. Par exemple, onchangeles déclencheurs d'événement textarea, inputet select. Pendant que l' onsubmitévénement se déclenche form. L' clickévénement déclenche toutes les autres requêtes. HTMX offre un "hx-trigger" unique si vous avez besoin de spécifier quel événement déclenchera la requête.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

Demande de déclenchement

CodePen-Link

Lorsque la souris survole l'élément div dans le code ci-dessus, elle envoie une requête GET au point de terminaison d'URL fourni et récupère les blagues.

Déclencher des modificateurs avec HTMX

Comme mentionné dans la section précédente, il est possible de modifier l' attribut hx-trigger pour changer son comportement. Par exemple, si vous souhaitez qu'une requête ne se produise qu'une seule fois, vous pouvez utiliser le oncemodificateur pour le déclencheur.

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

Vous trouverez ci-dessous les listes des modificateurs disponibles :

changed- envoyer une requête si la valeur de l'élément a changé.

display:<time interval>- attendre un certain temps (par exemple delay-1s) avant d'envoyer la requête.

throttle: <time interval>- attendre le temps imparti (par exemple delay-1s) avant d'envoyer la requête. Contrairement à delay , si un nouvel événement se produit avant qu'il n'atteigne la limite de temps, l'événement sera rejeté, ce qui signifie qu'il déclenche une demande à la fin du temps imparti.

form: <css selector>- écouter un événement sur un élément différent. Vous pouvez l'utiliser pour des choses comme les raccourcis clavier.

Vous pouvez utiliser tous ces attributs ci-dessus pour implémenter certains modèles UX courants tels que le modèle de zone de recherche active. Avec cet exemple ici , vous pouvez voir ces attributs ci-dessus en action.

Interrogation avec l' htmx-triggerattribut

En utilisant l'attribut de déclencheur HTMX, nous pouvons également spécifier que l'élément interroge l'URL donnée toutes les nsecondes au lieu d'attendre qu'un événement se produise.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

Ici, le HTMX demande au navigateur d'envoyer une requête GET à l' /V2.jokeapiURL toutes les 3 secondes et d'afficher la réponse dans l'élément div.

Interrogation avec HTMX

CodePen-Link

Indicateurs de demande

Étant donné que le navigateur ne fournit aucun retour, il est utile d'informer les utilisateurs que quelque chose se passe. Vous pouvez le faire avec HTML en utilisant la classe 'htmx-indicator'.

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

La classe 'htmx-indicator' définirait l'opacité de tout élément avec cette classe 0par défaut, le rendant caché mais présent dans le DOM. Lorsque vous cliquez sur le bouton 'load jokes', il ajoute la classe 'htmx-request', qui affiche l'indicateur de chargeur.

Demande-Indicateurs

CodePen-Link

Éléments de ciblage

Comme indiqué précédemment, HTMX charge la réponse à une requête AJAX dans l'élément qui a initié la requête. L'attribut 'hx-target' permet de charger la réponse dans un élément différent de celui qui a initié la requête. Le 'hx-target' acceptera un sélecteur CSS et chargera automatiquement la réponse AJAX dans l'élément cible :

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

Dans la démo ci-dessus, lorsque vous cliquez sur le load jokesbouton, il charge automatiquement la réponse dans l' divélément en dessous.

htmx_target

CodePen-Link

Échange

Comme hx-targetdans la section précédente, HTMX offre une manière différente de déterminer comment charger la réponse renvoyée par Ajax dans le Dom. Vous pouvez le faire en définissant l'attribut 'hx-swap' avec l'une des valeurs répertoriées ci-dessous :

  • innerHTML: Ceci est la valeur par défault; il insère le contenu dans l'élément cible envoyant la requête. outerHTML: Il remplace l'intégralité de l'élément cible par le contenu renvoyé.
  • afterbegin: Il ajoute la réponse avant le premier enfant à l'intérieur de l'élément cible.
  • beforebegin: ajoute la réponse en tant qu'élément parent de l'élément réel déclenchant la requête.
  • beforeend: Il ajoute la réponse après le dernier enfant de l'élément envoyant la requête.
  • afterend: comme le beforeend, ceci ajoute la réponse après l'élément envoyant la demande.
  • none: cette option n'ajoute ni ne préfixe une réponse d'une requête AJAX.

Voici un exemple de barre de progression défilante utilisant certains des attributs mentionnés ci-dessus ( https://htmx.org/examples/progress-bar ).

Synchronisation de la requête avec HTML

Parfois, vous aurez besoin de synchroniser les requêtes entre deux éléments. Supposons que vous souhaitiez qu'une requête d'un élément remplace les requêtes d'un autre élément, ou que vous souhaitiez attendre que les requêtes de l'autre élément soient terminées. Vous pouvez le faire en utilisant l' hx-syncattribut. Considérez le code ci-dessous :

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

Dans l'exemple ci-dessus, nous avons une soumission de formulaire et une inputdemande de validation individuelle. Sans utiliser hx-sync, lorsque vous remplissez le formulaire et que vous le soumettez, cela déclenche deux requêtes parallèles vers /changeet /validatesimultanément. Selon la documentation, l'utilisation hx-sync=" closest form:abort" sur l'entrée surveillera les demandes sur formet arrêtera les demandes d'entrée si une demande de formulaire est présente ou démarrera pendant que la demande d'entrée est en cours :

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

En utilisant cette approche, nous pouvons résoudre le problème de synchronisation entre les deux éléments de manière déclarative. Vous pouvez en savoir plus sur hx-syncl'attribut ici .

Téléchargement de fichiers avec HTML

Avec HTMX, vous pouvez créer un formulaire de téléchargement de fichier qui sera soumis via Ajax à votre backend pour traitement. Vous pouvez facilement envoyer des fichiers tels que des vidéos, des images et des documents. Vous pouvez implémenter cela avec HTMX en incorporant directement les hx-encodingattributs avec la valeur multipart/form-datadans l'élément parent envoyant la requête :

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

Validation des entrées avec HTML

Htmx s'intègre nativement avec l'API de validation HTML 5, donc si une entrée validable n'est pas valide, elle n'enverra pas de requête. Cette fonctionnalité s'applique à la fois aux requêtes AJAX et aux envois WebSockets. En outre, HTMX déclenche des événements autour de la validation que vous pouvez utiliser pour accrocher la validation personnalisée et la gestion des erreurs. Les événements suivants sont actuellement disponibles :

  • `htmx:validation : validate - utilisé pour ajouter une logique de validation personnalisée.
  • htmx:validation:failed` - cet événement se déclenche lorsqu'une validation d'élément renvoie false, par exemple, indiquant une entrée invalide.
  • htmx:validation: halted: Il appelle cet événement lorsqu'une demande n'est pas émise en raison d'erreurs de validation. Vous pouvez trouver des erreurs spécifiques dans l' event.detail.errorsobjet.

Considérez une entrée qui utilise l' htmx:validate:validateévénement pour s'assurer que l'entrée a la valeur Daviden utilisant hyperscript :

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

Il est important de noter que toutes les validations côté client doivent avoir lieu sur le serveur, car elles peuvent toujours être contournées.

Animations CSS avec HTML

Htmx vous permet d'utiliser des transitions CSS pour ajouter des animations et des transitions fluides à votre page Web en utilisant uniquement CSS et HTML sans JavaScript. HTMX offre une puissante extension d'animation appelée class-toolsqui vous permet de définir des classes CSS qui basculent sur ou hors de l'élément à l'aide de l' attribut classesou .data-classes

Vous pouvez utiliser l'extension en affectant l' classesattribut à un élément. La classesvaleur de l'attribut se compose de « runs » séparés par un caractère &. Dans une exécution, il appliquera les opérations de classe de manière séquentielle avec le délai spécifié. Ces opérations de classe sont add, remove, ou toggleaccompagnées d'un nom de classe CSS et éventuellement de deux-points : et d'un délai.

<div classes= “add sample-demo: 1s”></div>

Une fois le contenu du navigateur chargé, HTMX ajoutera automatiquement une nouvelle classe de sample-demoà la div après 1 seconde. Jetons un coup d'œil à cet exemple de démonstration ci-dessous :

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transition

CodePen-Link Vous pouvez en savoir plus sur la façon de créer une animation et une transition convaincantes avec HTMX ici .

HTMX s'intègre de manière transparente à différents frameworks côté serveur, bien que certains frameworks puissent proposer des alternatives pour l'installation de HTMX. Consultez ce lien pour découvrir comment vous pouvez intégrer HTMX avec différents frameworks côté serveur.

Conclusion

HTMX est une technologie incroyable, et j'en suis ravi et j'ai hâte de l'utiliser en production sur mon prochain projet. Dans ce didacticiel, nous avons exploré comment installer HTMX, envoyer des requêtes Ajax, télécharger des fichiers, valider des entrées et créer des transitions CSS sans utiliser javaScript côté client.

Consultez ce lien pour explorer certains ensembles de démos de modèles UX implémentés avec HTMX que vous pouvez modifier et intégrer à vos projets.

Le lien suivant ( https://htmx.org/examples/ ) contient des ensembles de démos de modèles UX que vous pouvez modifier et intégrer à vos projets.

Source : https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

HTMX : La Nouvelle Approche Pour Les Applications Web Sans JavaScript
郝 玉华

郝 玉华

1659357120

HTMX:无 JavaScript 网络应用程序的最新方法

根据文档,HTMX库允许您在不使用 Javascript 的情况下添加现代浏览器功能。它使您可以直接在 HTML 中访问CSS 转换AJAXWebSockets服务器发送事件,使用属性快速构建现代用户界面。是否可以在没有 JavaScript 的情况下在客户端开发 Web 应用程序?在本教程中,我们将探索 HTMX 的所有令人兴奋的功能。您将学习如何在不编写 JavaScript 代码的情况下发送 Ajax 请求、上传文件、验证输入和触发 CSS 转换。

什么是 HTMX,为什么它很重要?

2013 年,Carson Gross 创建了一个替代前端库intercooler.js,其标语为“Ajax With Attributes”,以简化前端 Web 开发的复杂性。intercooler.js 的新版本达到了 2.0 版,并成为htmx ,被描述为一个库,使您能够直接在 HTML 中访问 Ajax、WebSockets、CSS 转换和服务器发送事件。

HTMX 创建者表示,它试图通过使用 Web 的原始模型来创建 Web 应用程序来利用 HTML 的力量。使用这种方法,开发人员不必编写 JavaScript 来实现类似的功能。相反,他们使用额外的 HTML 属性来实现动态内容和更新。根据 Gross 的说法,这些是 htmx 背后的动机:

  • 为什么只应该<a>并且<form>能够发出 HTTP 请求?
  • 为什么只有click&submit事件会触发它们?
  • 为什么只有GET&POST方法可用?
  • 为什么只能更换entire屏幕?

“通过消除任意约束,htmx 将 HTML 完成为超文本,”他总结道。

使用 HTMX,开发人员可以使用最少的 HTML 和样式实现多个UI 功能和 UX 模式,例如进度条延迟加载无限滚动内联验证等。

HTMX 方法不同于 Vue.js 和 React 等其他前端框架,其中客户端应用程序使用 JavaScript 从服务器请求信息并以 JSON 格式接收信息。使用 HTMX,当您向服务器发出请求时,端点将返回完整的 Html 并更新部分页面。您可以将 HTMX 与任何服务器端技术集成,因为应用程序逻辑发生在后端。

设置 HTMX

要设置 HTMX,您似乎可以通过 CDN 加载它并将其添加到您的 head 标签中,如下所示:

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

另一种方法是下载htmx.min.js 源文件并将其添加到项目中的相应目录中,然后在必要时使用如下脚本标记将其插入:

<script src="/path/to/htmx.min.js"></script>

您也可以通过npm以下方式安装 HTMX:

npm install htmx.org

使用 HTMX 发送 Ajax 请求

HTMX 提供了一组属性,使您能够直接从 HTML 发出 AJAX 请求。

  • hx-post- 向给定 URL 发出 POST 请求。
  • hx-get- 向给定 URL 发出 GET 请求。
  • hx-put- 向给定 URL 发出 PUT 请求。
  • hx-patch- 向给定 URL 发出 PATCH 请求。
  • hx-delete- 向给定 URL 发出 DELETE 请求。

上面的每个属性都接受一个 URL 来发送 AJAX 请求。因此,每当触发元素时,它都会向给定的 URL 发送指定类型的请求。考虑下面的例子:

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

上面的演示告诉浏览器,当用户单击元素时,它应该向jokeapi 端点 URL ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-modeLoad Jokes )发送GET请求 ( ) 并加载响应到 div 元素。我们在这里使用了一个演示笑话 API,一个 REST API 提供统一且格式良好的笑话。hx-get

Htmx-Demo

Codepen 链接

接下来,我们将研究如何将响应加载到另一个 HTML 元素中。

使用 HTMX 触发请求

默认情况下,元素的“自然”事件会自动启动 Ajax 请求。例如,onchange事件触发器textareainputselect。而onsubmit事件触发form。该click事件触发所有其他请求。如果您需要指定哪个事件将触发请求,HTMX 提供了一个独特的“hx-trigger”。

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

触发请求

CodePen-Link

当鼠标悬停在上面代码中的 div 元素上时,它会向提供的 URL 端点发送一个 GET 请求并检索笑话。

使用 HTMX 触发修饰符

如上一节所述,可以修改hx-trigger属性以改变其行为。例如,如果您只希望请求发生一次,您可以使用once触发器的修饰符。

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

以下是可用修饰符的列表:

changed- 如果元素值已更改,则发送请求。

display:<time interval>delay-1s-在发送请求之前等待给定的时间(例如)。

throttle: <time interval>delay-1s-在发送请求之前等待给定的时间量(例如)。与delay不同的是,如果一个新事件在达到时间限制之前发生,该事件将被丢弃,这意味着它会在时间结束时触发请求。

form: <css selector>- 监听不同元素的事件。您可以将其用于键盘快捷键等操作。

您可以使用上述所有这些属性来实现一些常见的 UX 模式,例如 Active Search Box 模式。通过此处的示例,您可以在上面看到这些属性。

使用属性轮询htmx-trigger

使用 HTMX 触发器属性,我们还可以指定元素每秒轮询给定 URL,n而不是等待事件发生。

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

这里,HTMX 指示浏览器每 3 秒向/V2.jokeapiURL 发送一次 GET 请求,并在 div 元素中显示响应。

使用 HTMX 轮询

CodePen-Link

请求指标

因为浏览器不提供反馈,所以通知用户正在发生的事情会很有帮助。您可以使用 'htmx-indicator' 类对 HTMX 执行此操作。

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

默认情况下, “htmx-indicator”类会将具有此类的任何元素的不透明度设置为0默认值,使其隐藏但存在于 DOM 中。当您单击“加载笑话”按钮时,它会添加“htmx-request”类,该类会显示加载器指示器。

请求指标

CodePen-Link

定位元素

如前所述,HTMX 将对 AJAX 请求的响应加载到发起请求的元素中。'hx-target' 属性允许您将响应加载到与发起请求的元素不同的元素中。'hx-target' 将接受 CSS 选择器并自动将 AJAX 响应加载到目标元素中:

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

在上面的演示中,当你点击load jokes按钮时,它会自动将响应加载到div它下面的元素中。

htmx_target

CodePen-Link

交换

hx-target上一节中的一样,HTMX 提供了一种不同的方法来确定如何在 Dom 中加载 Ajax 返回的响应。您可以通过使用下面列出的任何值设置“hx-swap”属性来做到这一点:

  • innerHTML: 这是默认值; 它将内容插入到发送请求的目标元素中。outerHTML:它将整个目标元素替换为返回的内容。
  • afterbegin:它在目标元素内的第一个子元素之前添加响应。
  • beforebegin: 将响应添加为触发请求的实际元素的父元素。
  • beforeend:它在发送请求的元素的最后一个子元素之后附加响应。
  • afterend: 和 一样beforeend,这会在元素发送请求之后附加响应。
  • none:此选项不会附加或预先添加来自 AJAX 请求的响应。

这是使用上述某些属性的滚动进度条示例 ( https://htmx.org/examples/progress-bar )。

与 HTMX 同步请求

有时,您需要在两个元素之间同步请求。假设您希望一个元素的请求覆盖另一个元素的请求,或者您希望等到另一个元素的请求完成。您可以通过使用hx-sync属性来做到这一点。考虑下面的代码:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

在上面的示例中,我们有一个表单提交和一个单独的input验证请求。不使用hx-sync,当您填写表单并提交时,它会同时触发两个并行/change请求/validate。根据文档,hx-sync=" closest form:abort" 在输入上使用将监视 上的请求,form如果存在表单请求或在输入请求运行时开始,则停止输入请求:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

使用这种方法,我们可以以声明方式修复两个元素之间的同步问题。您可以在此处阅读有关hx-sync属性的更多信息。

使用 HTMX 上传文件

使用 HTMX,您可以创建一个文件上传表单,该表单将通过 Ajax 提交到您的后端进行处理。您可以毫不费力地发送视频、图像和文档等文件。您可以使用 HTMX 通过将hx-encoding具有值的属性直接嵌入multipart/form-data发送请求的父元素中来实现这一点:

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

使用 HTMX 进行输入验证

Htmx 与 HTML 5 Validation API 原生结合,因此如果可验证的输入无效,它将不会发送请求。此功能适用于 AJAX 请求和 WebSockets 发送。此外,HTMX 会围绕验证触发事件,您可以使用这些事件来挂钩自定义验证和错误处理。当前可用的事件如下:

  • `htmx:validation: validate - 用于添加自定义验证逻辑。
  • htmx:validation:failed` - 当元素验证返回 false 时触发此事件,例如,指示无效输入。
  • htmx:validation: halted:当您由于验证错误而未发出请求时,它会调用此事件。event.detail.errors您可以在对象中找到特定的错误。

考虑一个使用htmx:validate:validate事件来确保输入具有David使用hyperscript的值的输入:

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

需要注意的是,所有客户端验证都必须在服务器上进行,因为它总是可以被绕过。

使用 HTMX 的 CSS 动画

Htmx 使您能够使用CSS 过渡来为您的网页添加流畅的动画和过渡,只使用 CSS 和 HTML 而不使用 JavaScript。HTMX 提供了一个强大的动画扩展,它允许您定义 CSS 类,这些类可以使用or属性class-tools切换到元素上或从元素上切换下来。classesdata-classes

您可以通过将classes属性分配给元素来使用扩展。classes属性值由用 & 字符分隔的“运行”组成。在运行中,它将以指定的延迟顺序应用类操作。这些类操作是add, remove, 或toggle伴随着 CSS 类名和可选的冒号: 和时间延迟。

<div classes= “add sample-demo: 1s”></div>

sample-demo浏览器内容加载后,HTMX 会在 1 秒后自动为 div 添加一个新类。让我们看一下下面的这个演示示例:

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transition

CodePen-Link您可以在此处了解有关如何使用 HTMX 制作引人注目的动画和过渡的更多信息。

HTMX 与不同的服务器端框架无缝集成,尽管某些框架可能有安装 HTMX 的替代方案。查看此链接以探索如何将 HTMX 与不同的服务器端框架集成。

结论

HTMX 是一项令人难以置信的技术,我对它很兴奋,迫不及待地想在我的下一个项目的生产中使用它。在本教程中,我们探讨了如何在客户端不使用 javaScript 的情况下安装 HTMX、发送 Ajax 请求、上传文件、验证输入以及创建 CSS 过渡。

检查此链接以探索使用 HTMX 实现的一些UX 模式演示集,您可以对其进行编辑并与您的项目集成。

以下链接 ( https://htmx.org/examples/ ) 包含一些UX 模式演示集,您可以对其进行编辑并集成到您的项目中。

来源:https ://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

HTMX:无 JavaScript 网络应用程序的最新方法
Diego  Elizondo

Diego Elizondo

1659356719

HTMX: El Enfoque Más Nuevo Para Aplicaciones Web Sin JavaScript

De acuerdo con la documentación, la biblioteca HTMX le permite agregar funciones de navegador modernas sin usar Javascript. Le brinda acceso a transiciones CSS , AJAX , WebSockets y eventos enviados por el servidor directamente en HTML, utilizando atributos para crear interfaces de usuario modernas rápidamente. ¿Sería posible desarrollar aplicaciones web en el lado del cliente sin JavaScript? En este tutorial, exploraremos todas las características alucinantes de HTMX. Aprenderá a enviar solicitudes Ajax, cargar archivos, validar entradas y activar transiciones CSS sin escribir código JavaScript.

¿Qué es HTMX y por qué es importante?

En 2013, Carson Gross creó una biblioteca frontend alternativa , intercooler.js , con el lema "Ajax With Attributes" para simplificar la complejidad del desarrollo web frontend. Una nueva versión de intercooler.js alcanzó la versión 2.0 y se convirtió en htmx descrito como una biblioteca que le permite acceder a Ajax, WebSockets, transición CSS y eventos enviados por el servidor directamente dentro de HTML.

El creador de HTMX dice que intenta aprovechar el poder de HTML utilizando el modelo original de la web para crear aplicaciones web. Con este enfoque, los desarrolladores no tienen que escribir JavaScript para lograr una funcionalidad similar. En su lugar, utilizan atributos HTML adicionales para lograr contenido dinámico y actualizaciones. Según Gross, estas son las motivaciones detrás de htmx:

  • ¿Por qué solo debería <a>y <form>poder realizar solicitudes HTTP?
  • ¿Por qué solo los eventos click& deberían submitactivarlos?
  • ¿Por qué solo los métodos GET& deberían estar disponibles?POST
  • ¿Por qué solo debería poder reemplazar la entirepantalla?

“Al eliminar las restricciones arbitrarias, htmx completa HTML como un hipertexto”, concluye.

Con HTMX, los desarrolladores pueden implementar varias funciones de interfaz de usuario y patrones de experiencia de usuario con HTML y estilos mínimos, como barra de progreso , carga diferida , desplazamiento infinito , validación en línea y más .

El enfoque HTMX difiere de otros marcos frontend como Vue.js y React, donde la aplicación del lado del cliente usa JavaScript para solicitar información del servidor y recibirla en formato JSON. Con HTMX, cuando realiza una solicitud al servidor, el punto final devolverá Html completamente formado y actualizará parte de la página. Puede integrar HTMX con cualquier tecnología del lado del servidor, ya que la lógica de la aplicación ocurre en el backend.

Configurando HTMX

Para configurar HTMX, aparentemente puede cargarlo a través de un CDN y agregarlo a su etiqueta principal como se muestra a continuación:

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

Otra forma es descargar el archivo fuente htmx.min.js y agregarlo al directorio apropiado en su proyecto, luego insertarlo donde sea necesario con una etiqueta de secuencia de comandos como esta:

<script src="/path/to/htmx.min.js"></script>

También puede instalar HTMX a través npmde esto a continuación:

npm install htmx.org

Envío de solicitudes Ajax usando HTMX

HTMX ofrece un conjunto de atributos que le permiten realizar solicitudes AJAX directamente desde HTML.

  • hx-post- emite una solicitud POST a la URL dada.
  • hx-get- emite una solicitud GET a la URL dada.
  • hx-put- emite una solicitud PUT a la URL dada.
  • hx-patch- emite una solicitud PATCH a la URL dada.
  • hx-delete- emite una solicitud DELETE a la URL dada.

Cada uno de estos atributos anteriores acepta una URL para enviar una solicitud AJAX. Entonces, cada vez que se activa el elemento, envía el tipo de solicitud especificado a la URL dada. Considere el siguiente ejemplo:

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

La demostración anterior indica al navegador que cuando un usuario hace clic en el Load Jokeselemento, debe enviar una GETsolicitud ( hx-get) a la URL del punto final de jokeapi ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode ) y cargar el respuesta en el elemento div. Usamos una API de broma de demostración aquí, una API REST que sirve bromas de manera uniforme y con un buen formato.

Htmx-Demostración

Enlace de código abierto

A continuación, examinaremos cómo cargar la respuesta en otro elemento HTML.

Activación de solicitudes con HTMX

El evento "natural" de un elemento inicia solicitudes Ajax automáticamente de forma predeterminada. Por ejemplo, onchangedesencadenadores de eventos textarea, inputy select. Mientras onsubmitse desencadena el evento form. El clickevento desencadena cualquier otra solicitud. HTMX ofrece un 'hx-trigger' único si necesita especificar qué evento activará la solicitud.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

Solicitud de activación

CodePen-Link

Cuando el mouse pasa sobre el elemento div en el código anterior, envía una solicitud GET al punto final de la URL proporcionada y recupera los chistes.

Activación de modificadores con HTMX

Como se mencionó en la sección anterior, es posible modificar el atributo hx-trigger para cambiar su comportamiento. Por ejemplo, si solo desea que una solicitud ocurra una vez, puede usar el oncemodificador para el disparador.

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

A continuación se muestran las listas de modificadores disponibles:

changed- enviar una solicitud si el valor del elemento ha cambiado.

display:<time interval>- esperar una determinada cantidad de tiempo (p. ej delay-1s.) antes de enviar la solicitud.

throttle: <time interval>- esperar la cantidad de tiempo dada (por ejemplo delay-1s) antes de enviar la solicitud. A diferencia de delay , si ocurre un nuevo evento antes de que alcance el límite de tiempo, el evento se descartará, lo que significa que activa una solicitud al final del tiempo.

form: <css selector>- escuche el evento en un elemento diferente. Puede usar esto para cosas como atajos de teclado.

Puede usar todos estos atributos anteriores para implementar algunos patrones comunes de UX como el patrón del cuadro de búsqueda activa. Con este ejemplo aquí , puede ver estos atributos en acción.

Sondeo con el htmx-triggeratributo

Usando el atributo de activación HTMX, también podemos especificar que el elemento sondee la URL dada cada nsegundos en lugar de esperar a que ocurra un evento.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

Aquí, HTMX le indica al navegador que envíe una solicitud GET a la /V2.jokeapiURL cada 3 segundos y muestre la respuesta en el elemento div.

Sondeo con HTMX

CodePen-Link

Indicadores de solicitud

Debido a que el navegador no proporciona comentarios, es útil notificar a los usuarios que algo está sucediendo. Puede hacer esto con HTMX usando la clase 'htmx-indicator'.

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

La clase 'htmx-indicator' establecería la opacidad de cualquier elemento con esta clase 0por defecto, haciéndolo oculto pero presente en el DOM. Cuando hace clic en el botón 'cargar chistes', agrega la clase 'htmx-request', que muestra el indicador del cargador.

Indicadores de solicitud

CodePen-Link

Elementos de orientación

Como se indicó anteriormente, HTMX carga la respuesta a una solicitud AJAX en el elemento que inició la solicitud. El atributo 'hx-target' le permite cargar la respuesta en un elemento diferente al que inició la solicitud. El 'hx-target' aceptará un selector de CSS y cargará automáticamente la respuesta AJAX en el elemento de destino:

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

En la demostración anterior, cuando hace clic en el load jokesbotón, cargará automáticamente la respuesta en el divelemento que se encuentra debajo.

htmx_objetivo

CodePen-Link

Intercambio

Al igual que hx-targeten la sección anterior, HTMX ofrece una forma diferente de determinar cómo cargar la respuesta devuelta por Ajax dentro del Dom. Puede hacerlo configurando el atributo 'hx-swap' con cualquiera de los valores que se enumeran a continuación:

  • innerHTML: Este es el valor predeterminado; inserta el contenido en el elemento de destino que envía la solicitud. outerHTML: Reemplaza todo el elemento de destino con el contenido devuelto.
  • afterbegin: Antepone la respuesta antes del primer elemento secundario dentro del elemento de destino.
  • beforebegin: antepone la respuesta como un elemento principal del elemento real que activa la solicitud.
  • beforeend: Agrega la respuesta después del último hijo del elemento que envía la solicitud.
  • afterend: como el beforeend, esto agrega la respuesta después de la solicitud de envío del elemento.
  • none: esta opción no agrega ni antepone una respuesta de una solicitud AJAX.

Aquí hay un ejemplo de una barra de progreso de desplazamiento que usa algunos de los atributos mencionados anteriormente ( https://htmx.org/examples/progress-bar ).

Solicitud de sincronización con HTMX

A veces, necesitará sincronizar solicitudes entre dos elementos. Suponga que desea que una solicitud de un elemento anule las solicitudes de otro elemento, o desea esperar hasta que se completen las solicitudes del otro elemento. Puedes hacer esto usando el hx-syncatributo. Considere el siguiente código:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

En el ejemplo anterior, tenemos un envío de formulario y una inputsolicitud de validación individual. Sin usar hx-sync, cuando completa el formulario y lo envía, se activan dos solicitudes paralelas /changey /validatesimultáneas. De acuerdo con la documentación, el uso hx-sync=" closest form:abort" de la entrada observará las solicitudes en el formy detendrá las solicitudes de entrada si hay una solicitud de formulario presente o comenzará mientras la solicitud de entrada está en vuelo:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

Con este enfoque, podemos solucionar el problema de sincronización entre los dos elementos de forma declarativa. Puede leer más sobre el hx-syncatributo aquí .

Carga de archivos con HTMX

Con HTMX, puede crear un formulario de carga de archivos que se enviará a través de Ajax a su backend para su procesamiento. Puede enviar sin esfuerzo archivos como videos, imágenes y documentos. Puede implementar esto con HTMX incrustando directamente los hx-encodingatributos con el valor multipart/form-dataen el elemento principal que envía la solicitud:

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

Validación de entrada con HTMX

Htmx se incorpora de forma nativa con la API de validación de HTML 5, por lo que si una entrada validable no es válida, no enviará una solicitud. Esta función se aplica tanto a las solicitudes de AJAX como a los envíos de WebSockets. Además, HTMX activa eventos en torno a la validación que puede usar para vincular la validación personalizada y el manejo de errores. Actualmente están disponibles los siguientes eventos:

  • `htmx:validación: validar: se usa para agregar lógica de validación personalizada.
  • htmx:validation:failed`: este evento se activa cuando la validación de un elemento devuelve falso, por ejemplo, indica una entrada no válida.
  • htmx:validation: halted: Llama a este evento cuando no se emite una solicitud debido a errores de validación. Puede encontrar errores específicos en el event.detail.errorsobjeto.

Considere una entrada que use el htmx:validate:validateevento para asegurarse de que la entrada tenga el valor Davidusando hiperíndice :

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

Es importante tener en cuenta que toda la validación del lado del cliente debe ocurrir en el servidor, ya que siempre se puede omitir.

Animaciones CSS con HTMX

Htmx le permite usar transiciones CSS para agregar animaciones y transiciones suaves a su página web usando solo CSS y HTML sin JavaScript. HTMX ofrece una poderosa extensión de animación llamada class-toolsque le permite definir clases de CSS que se intercambian dentro o fuera del elemento usando el atributo classeso .data-classes

Puede usar la extensión asignando el classesatributo a un elemento. El classesvalor del atributo consta de "ejecuciones" separadas por un carácter &. En una ejecución, aplicará operaciones de clase secuencialmente con el retraso especificado. Estas operaciones de clase son add, removeo togglevan acompañadas de un nombre de clase CSS y, opcionalmente, de dos puntos: y un retraso de tiempo.

<div classes= “add sample-demo: 1s”></div>

Una vez que se cargue el contenido del navegador, HTMX agregará automáticamente una nueva clase de sample-demoal div después de 1 segundo. Echemos un vistazo a este ejemplo de demostración a continuación:

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transición

CodePen-Link Puede obtener más información sobre cómo hacer animaciones y transiciones convincentes con HTMX aquí .

HTMX se integra a la perfección con diferentes marcos del lado del servidor, aunque algunos marcos pueden tener alternativas para instalar HTMX. Consulte este enlace para explorar cómo puede integrar HTMX con diferentes marcos del lado del servidor.

Conclusión

HTMX es una tecnología increíble y estoy entusiasmado con ella y no veo la hora de usarla en la producción de mi próximo proyecto. En este tutorial, exploramos cómo instalar HTMX, enviar solicitudes Ajax, cargar archivos, validar entradas y crear transiciones CSS sin usar JavaScript en el lado del cliente.

Consulte este enlace para explorar algunos conjuntos de demostración de patrones UX implementados con HTMX que puede editar e integrar con sus proyectos.

El siguiente enlace ( https://htmx.org/examples/ ) contiene algunos conjuntos de demostraciones de patrones de UX que puede editar e integrar en sus proyectos.

Fuente: https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-sin-javascript

#javascript #htmx 

HTMX: El Enfoque Más Nuevo Para Aplicaciones Web Sin JavaScript

HTMX: A Mais Nova Abordagem Para Aplicativos Da Web Sem JavaScript

De acordo com a documentação, a biblioteca HTMX permite adicionar recursos de navegadores modernos sem usar Javascript. Ele fornece acesso a Transições CSS , AJAX , WebSockets e Eventos Enviados pelo Servidor diretamente em HTML, usando atributos para construir interfaces de usuário modernas rapidamente. Seria possível desenvolver aplicativos da web no lado do cliente sem JavaScript? Neste tutorial, exploraremos todos os recursos alucinantes do HTMX. Você aprenderá como enviar solicitações Ajax, fazer upload de arquivos, validar entradas e acionar transições CSS sem escrever código JavaScript.

O que é HTMX e por que é importante?

Em 2013, Carson Gross criou uma biblioteca de front-end alternativa , intercooler.js , com o slogan “Ajax With Attributes” para simplificar a complexidade do desenvolvimento web de front-end. Uma nova versão do intercooler.js chegou à versão 2.0 e tornou-se htmx descrita como uma biblioteca que permite acessar Ajax, WebSockets, transição CSS e eventos enviados pelo servidor diretamente dentro do HTML.

O criador do HTMX diz que tenta aproveitar o poder do HTML usando o modelo original da web para criar aplicativos da web. Com essa abordagem, os desenvolvedores não precisam escrever JavaScript para obter funcionalidade semelhante. Em vez disso, eles usam atributos HTML extras para obter conteúdo dinâmico e atualizações. De acordo com Gross, estas são as motivações por trás do htmx:

  • Por que só deve <a>e <form>pode fazer solicitações HTTP?
  • Por que apenas click& submiteventos devem acioná-los?
  • Por que apenas GET& POSTmétodos devem estar disponíveis?
  • Por que você só pode substituir a entiretela?

“Ao remover as restrições arbitrárias, o htmx completa o HTML como um hipertexto”, conclui.

Com o HTMX, os desenvolvedores podem implementar vários recursos de interface do usuário e padrões de UX com HTML e estilos mínimos, como Barra de Progresso , Carregamento Preguiçoso , Rolagem Infinita , Validação Inline e muito mais .

A abordagem HTMX difere de outras estruturas de front-end, como Vue.js e React, em que o aplicativo do lado do cliente usa JavaScript para solicitar informações do servidor e recebê-las em formato JSON. Com o HTMX, quando você faz uma solicitação ao servidor, o endpoint retornará o Html totalmente formado e atualizará parte da página. Você pode integrar o HTMX com qualquer tecnologia do lado do servidor, pois a lógica do aplicativo acontece no back-end.

Configurando o HTMX

Para configurar o HTMX, você pode aparentemente carregá-lo por meio de um CDN e adicioná-lo à sua tag head como esta abaixo:

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

Outra maneira é baixar o arquivo de origem htmx.min.js e adicioná-lo ao diretório apropriado em seu projeto e inseri-lo quando necessário com uma tag de script como esta:

<script src="/path/to/htmx.min.js"></script>

Você também pode instalar o HTMX via npmassim abaixo:

npm install htmx.org

Enviando solicitações Ajax usando HTMX

O HTMX oferece um conjunto de atributos que permitem fazer solicitações AJAX diretamente do HTML.

  • hx-post- emite uma solicitação POST para a URL fornecida.
  • hx-get- emite uma solicitação GET para o URL fornecido.
  • hx-put- emite uma solicitação PUT para a URL fornecida.
  • hx-patch- emite uma solicitação PATCH para o URL fornecido.
  • hx-delete- emite uma solicitação DELETE para o URL fornecido.

Cada um desses atributos acima aceita uma URL para enviar uma solicitação AJAX. Portanto, sempre que o elemento é acionado, ele envia o tipo de solicitação especificado para o URL fornecido. Considere o exemplo abaixo:

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

A demonstração acima instrui o navegador que quando um usuário clica no Load Jokeselemento, ele deve enviar uma GETsolicitação ( hx-get) para a URL do endpoint jokeapi ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode ) e carregar o resposta no elemento div. Usamos uma API de demonstração de piadas aqui, uma API REST que serve piadas uniformemente e bem formatadas.

Htmx-Demo

Link Codepen

A seguir, examinaremos como carregar a resposta em outro elemento HTML.

Acionando solicitações com HTMX

O evento “natural” de um elemento inicia solicitações Ajax automaticamente por padrão. Por exemplo, onchangeacionadores textareade eventos input, e select. Enquanto o onsubmitevento é acionado form. O clickevento aciona todas as outras solicitações. O HTMX oferece um 'hx-trigger' exclusivo se você precisar especificar qual evento acionará a solicitação.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

Solicitação de acionamento

CodePen-Link

Quando o mouse passa sobre o elemento div no código acima, ele envia uma solicitação GET para o endpoint de URL fornecido e recupera as piadas.

Acionando modificadores com HTMX

Conforme mencionado na seção anterior, é possível modificar o atributo hx-trigger para alterar seu comportamento. Por exemplo, se você deseja que uma solicitação ocorra apenas uma vez, você pode usar o oncemodificador para o gatilho.

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

Abaixo estão as listas de modificadores disponíveis:

changed- enviar uma solicitação se o valor do elemento foi alterado.

display:<time interval>- aguarde um determinado período de tempo (por exemplo delay-1s) antes de enviar a solicitação.

throttle: <time interval>- aguarde o tempo determinado (por exemplo delay-1s, ) antes de enviar a solicitação. Ao contrário de delay , se um novo evento ocorrer antes de atingir o limite de tempo, o evento será descartado, o que significa que ele aciona uma solicitação ao final do tempo.

form: <css selector>- ouvir o evento em um elemento diferente. Você pode usar isso para coisas como atalhos de teclado.

Você pode usar todos esses atributos acima para implementar alguns padrões comuns de UX, como o padrão Active Search Box. Com este exemplo aqui , você pode ver esses atributos acima em ação.

Sondagem com o htmx-triggeratributo

Usando o atributo de gatilho HTMX, também podemos especificar que o elemento pesquisa a URL fornecida a cada nsegundos, em vez de aguardar a ocorrência de um evento.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

Aqui, o HTMX instrui o navegador a enviar uma solicitação GET para a /V2.jokeapiURL a cada 3s e exibir a resposta no elemento div.

Sondagem com HTMX

CodePen-Link

Indicadores de solicitação

Como o navegador não fornece feedback, é útil notificar os usuários de que algo está acontecendo. Você pode fazer isso com HTMX usando a classe 'htmx-indicator'.

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

A classe 'htmx-indicator' definiria a opacidade de qualquer elemento com essa classe 0por padrão, tornando-o oculto, mas presente no DOM. Quando você clica no botão 'carregar piadas', ele adiciona a classe 'htmx-request', que exibe o indicador do carregador.

Indicadores de solicitação

CodePen-Link

Elementos de segmentação

Como dito anteriormente, o HTMX carrega a resposta a uma solicitação AJAX no elemento que iniciou a solicitação. O atributo 'hx-target' permite carregar a resposta em um elemento diferente daquele que iniciou a solicitação. O 'hx-target' aceitará um seletor CSS e carregará automaticamente a resposta AJAX no elemento de destino:

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

Na demonstração acima, quando você clicar no load jokesbotão, ele carregará automaticamente a resposta no divelemento abaixo dele.

htmx_target

CodePen-Link

Trocando

Assim como hx-targetna seção anterior, o HTMX oferece uma maneira diferente de determinar como carregar a resposta retornada pelo Ajax dentro do Dom. Você pode fazer isso definindo o atributo 'hx-swap' com qualquer um dos valores listados abaixo:

  • innerHTML: Este é o valor padrão; ele insere o conteúdo no elemento de destino enviando a solicitação. outerHTML: substitui todo o elemento de destino pelo conteúdo retornado.
  • afterbegin: ele precede a resposta antes do primeiro filho dentro do elemento de destino.
  • beforebegin: precede a resposta como um elemento pai do elemento real que aciona a solicitação.
  • beforeend: anexa a resposta após o último filho do elemento que envia a solicitação.
  • afterend: como o beforeend, anexa a resposta após o elemento enviar a solicitação.
  • none: esta opção não anexa ou precede uma resposta de uma solicitação AJAX.

Aqui está um exemplo de uma barra de progresso de rolagem usando alguns dos atributos mencionados acima ( https://htmx.org/examples/progress-bar ).

Sincronizando solicitação com HTMX

Às vezes, você precisará sincronizar solicitações entre dois elementos. Suponha que você queira que uma solicitação de um elemento substitua as solicitações de outro elemento ou queira esperar até que as solicitações do outro elemento sejam concluídas. Você pode fazer isso usando o hx-syncatributo. Considere o código abaixo:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

No exemplo acima, temos um envio de formulário e uma inputsolicitação de validação individual. Sem usar hx-sync, ao preencher o formulário e enviá-lo, ele aciona duas solicitações paralelas para /changee /validatesimultaneamente. De acordo com a documentação, o uso hx-sync=" closest form:abort" na entrada observará as solicitações forme interromperá as solicitações de entrada se uma solicitação de formulário estiver presente ou iniciará enquanto a solicitação de entrada estiver em andamento:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

Usando essa abordagem, podemos corrigir o problema de sincronização entre os dois elementos de forma declarativa. Você pode ler mais sobre hx-synco atributo aqui .

Upload de arquivo com HTMX

Com o HTMX, você pode criar um formulário de upload de arquivo que será enviado via Ajax ao seu back-end para processamento. Você pode enviar facilmente arquivos como vídeos, imagens e documentos. Você pode implementar isso com HTMX incorporando diretamente os hx-encodingatributos com o valor multipart/form-datano elemento pai enviando a solicitação:

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

Validação de entrada com HTMX

Htmx é incorporado nativamente com a API de validação HTML 5, portanto, se uma entrada validável for inválida, ela não enviará uma solicitação. Esse recurso se aplica a solicitações AJAX e envios de WebSockets. Além disso, o HTMX dispara eventos em torno da validação que você pode usar para conectar a validação personalizada e o tratamento de erros. Os seguintes eventos estão atualmente disponíveis:

  • `htmx:validation: validate – usado para adicionar lógica de validação personalizada.
  • htmx:validation:failed` – este evento é acionado quando uma validação de elemento retorna false, por exemplo, indicando uma entrada inválida.
  • htmx:validation: halted: ele chama esse evento quando uma solicitação não é emitida devido a erros de validação. Você pode encontrar erros específicos no event.detail.errorsobjeto.

Considere uma entrada que usa o htmx:validate:validateevento para garantir que a entrada tenha o valor Davidusando hyperscript :

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

É importante observar que toda validação do lado do cliente deve ocorrer no servidor, pois sempre pode ser ignorada.

Animações CSS com HTMX

Htmx permite que você use transições CSS para adicionar animações e transições suaves à sua página da web usando apenas CSS e HTML sem JavaScript. O HTMX oferece uma poderosa extensão de animação chamada class-toolsque permite definir classes CSS que alternam para dentro ou para fora do elemento usando o atributo classesou .data-classes

Você pode usar a extensão atribuindo o classesatributo a um elemento. O classesvalor do atributo consiste em “execuções” separadas por um caractere &. Em uma execução, ele aplicará as operações de classe sequencialmente com o atraso especificado. Essas operações de classe são add, remove, ou toggleacompanhadas por um nome de classe CSS e, opcionalmente, por dois pontos: e atraso de tempo.

<div classes= “add sample-demo: 1s”></div>

Assim que o conteúdo do navegador for carregado, o HTMX adicionará automaticamente uma nova classe de sample-demoà div após 1 segundo. Vamos dar uma olhada neste exemplo de demonstração abaixo:

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transition

CodePen-Link Você pode aprender mais sobre como fazer animações e transições atraentes com HTMX aqui .

O HTMX se integra perfeitamente a diferentes estruturas do lado do servidor, embora algumas estruturas possam ter alternativas para instalar o HTMX. Confira este link para explorar como você pode integrar o HTMX com diferentes estruturas do lado do servidor.

Conclusão

HTMX é uma tecnologia incrível, estou empolgado com ela e mal posso esperar para usá-la em produção no meu próximo projeto. Neste tutorial, exploramos como instalar o HTMX, enviar solicitações Ajax, fazer upload de arquivos, validar entradas e criar transições CSS sem usar javaScript no lado do cliente.

Verifique este link para explorar alguns conjuntos de demonstração de padrões UX implementados com HTMX que você pode editar e integrar com seus projetos.

O link a seguir ( https://htmx.org/examples/ ) contém alguns conjuntos de demonstrações de padrões de UX que você pode editar e integrar em seus projetos.

Fonte: https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

HTMX: A Mais Nova Abordagem Para Aplicativos Da Web Sem JavaScript
Thai  Son

Thai Son

1659352931

HTMX: Cách Tiếp Cận Mới Nhất Cho Các ứng Dụng Web Không Sử Dụng JS

Theo tài liệu, thư viện HTMX cho phép bạn thêm các tính năng hiện đại của trình duyệt mà không cần sử dụng Javascript. Nó cung cấp cho bạn quyền truy cập vào Chuyển tiếp CSS , AJAX , WebSocketsSự kiện do máy chủ gửi trực tiếp trong HTML, sử dụng các thuộc tính để xây dựng giao diện người dùng hiện đại một cách nhanh chóng. Có thể phát triển các ứng dụng web ở phía máy khách mà không có JavaScript không? Trong hướng dẫn này, chúng ta sẽ khám phá tất cả các tính năng hấp dẫn của HTMX. Bạn sẽ học cách gửi yêu cầu Ajax, tải tệp lên, xác thực đầu vào và kích hoạt chuyển đổi CSS mà không cần viết mã JavaScript.

HTMX là gì và tại sao nó lại quan trọng?

Vào năm 2013, Carson Gross đã tạo ra một thư viện giao diện người dùng thay thế intercooler.js , với khẩu hiệu “Ajax With Attributes” để đơn giản hóa sự phức tạp của phát triển web giao diện người dùng. Một phiên bản mới của intercooler.js đã đạt đến phiên bản 2.0 và trở thành htmx được mô tả như một thư viện cho phép bạn truy cập Ajax, WebSockets, chuyển tiếp CSS và Sự kiện do máy chủ gửi trực tiếp bên trong HTML.

Người tạo HTMX cho biết họ cố gắng tận dụng sức mạnh của HTML bằng cách sử dụng mô hình gốc của web để tạo các ứng dụng web. Với cách tiếp cận này, các nhà phát triển không phải viết JavaScript để đạt được chức năng tương tự. Thay vào đó, họ sử dụng các thuộc tính HTML bổ sung để đạt được nội dung động và cập nhật. Theo Gross, đây là động lực đằng sau htmx:

  • Tại sao chỉ nên <a><form>có thể thực hiện các yêu cầu HTTP?
  • Tại sao chỉ click& submitsự kiện nên kích hoạt chúng?
  • Tại sao chỉ nên GET& POSTphương pháp có sẵn?
  • Tại sao bạn chỉ có thể thay entiremàn hình?

Ông kết luận: “Bằng cách loại bỏ các ràng buộc tùy ý, htmx hoàn thiện HTML như một siêu văn bản.

Với HTMX, các nhà phát triển có thể triển khai một số tính năng giao diện người dùng và các mẫu UX với HTML và kiểu dáng tối thiểu như Thanh tiến trình , Tải chậm , Cuộn vô hạn , Xác thực nội tuyếnhơn thế nữa .

Cách tiếp cận HTMX khác với các khuôn khổ giao diện người dùng khác như Vue.js và React, trong đó ứng dụng phía máy khách sử dụng JavaScript để yêu cầu thông tin từ máy chủ và nhận nó ở định dạng JSON. Với HTMX, khi bạn đưa ra yêu cầu với máy chủ, điểm cuối sẽ trả về Html đã được định dạng đầy đủ và sẽ cập nhật một phần của trang. Bạn có thể tích hợp HTMX với bất kỳ công nghệ phía máy chủ nào vì logic ứng dụng xảy ra trên phần phụ trợ.

Thiết lập HTMX

Để thiết lập HTMX, dường như bạn có thể tải nó qua CDN và thêm nó vào thẻ head của bạn như sau:

<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script

Một cách khác là tải xuống tệp nguồn htmx.min.js và thêm nó vào thư mục thích hợp trong dự án của bạn, sau đó chèn nó vào nơi cần thiết bằng một thẻ script như sau:

<script src="/path/to/htmx.min.js"></script>

Bạn cũng có thể cài đặt HTMX thông qua npmnhư sau:

npm install htmx.org

Gửi yêu cầu Ajax bằng HTMX

HTMX cung cấp một tập hợp các thuộc tính cho phép bạn thực hiện các yêu cầu AJAX trực tiếp từ HTML.

  • hx-post- đưa ra một yêu cầu ĐĂNG tới URL đã cho.
  • hx-get- đưa ra yêu cầu GET đến URL đã cho.
  • hx-put- đưa ra một yêu cầu PUT đến URL đã cho.
  • hx-patch- đưa ra yêu cầu PATCH tới URL đã cho.
  • hx-delete- đưa ra yêu cầu XÓA đối với URL đã cho.

Mỗi thuộc tính ở trên chấp nhận một URL để gửi một yêu cầu AJAX đến. Vì vậy, bất cứ khi nào phần tử được kích hoạt, nó sẽ gửi loại yêu cầu được chỉ định đến URL nhất định. Hãy xem xét ví dụ dưới đây:

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div
  hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode"
>Load Jokes</div>

Bản demo ở trên hướng dẫn trình duyệt rằng khi người dùng nhấp vào Load Jokesphần tử, nó sẽ gửi một GETyêu cầu ( hx-get) đến URL điểm cuối jokeapi ( https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode ) và tải phản hồi vào phần tử div. Chúng tôi đã sử dụng một API Joke demo ở đây, một API REST phục vụ các trò đùa được định dạng tốt và thống nhất.

Htmx-Demo

Liên kết Codepen

Tiếp theo, chúng ta sẽ kiểm tra cách tải phản hồi vào một phần tử HTML khác.

Kích hoạt yêu cầu với HTMX

Sự kiện “tự nhiên” của một phần tử sẽ tự động khởi tạo các yêu cầu Ajax theo mặc định. Ví dụ: onchangetrình kích hoạt sự textareakiện inputselect. Trong khi onsubmitsự kiện kích hoạt form. Sự clickkiện kích hoạt mọi yêu cầu khác. HTMX cung cấp một 'hx-trigger' duy nhất nếu bạn cần chỉ định sự kiện nào sẽ kích hoạt yêu cầu.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter”
>
 Load Jokes
</div>

Yêu cầu kích hoạt

CodePen-Link

Khi di chuột qua phần tử div trong đoạn mã trên, nó sẽ gửi yêu cầu GET đến điểm cuối URL được cung cấp và truy xuất Truyện cười.

Kích hoạt Modifier với HTMX

Như đã đề cập trong phần trước, có thể sửa đổi thuộc tính hx-trigger để thay đổi hành vi của nó. Ví dụ: nếu bạn chỉ muốn một yêu cầu xuất hiện một lần, bạn có thể sử dụng công oncecụ sửa đổi cho trình kích hoạt.

<div class= "jokes" 
hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" 
hx-trigger="mouseenter once”
>
      Load Jokes
</div>

Dưới đây là danh sách các công cụ sửa đổi có sẵn:

changed- gửi yêu cầu nếu giá trị phần tử đã thay đổi.

display:<time interval>- đợi một khoảng thời gian nhất định (ví dụ delay-1s) trước khi gửi yêu cầu.

throttle: <time interval>- đợi một khoảng thời gian nhất định (ví dụ delay-1s) trước khi gửi yêu cầu. Không giống như sự chậm trễ , nếu một sự kiện mới xảy ra trước khi nó đạt đến giới hạn thời gian, thì sự kiện đó sẽ bị loại bỏ, có nghĩa là nó sẽ kích hoạt một yêu cầu vào cuối thời gian.

form: <css selector>- lắng nghe sự kiện trên một phần tử khác. Bạn có thể sử dụng nó cho những thứ như phím tắt.

Bạn có thể sử dụng tất cả các thuộc tính ở trên để triển khai một số mẫu UX phổ biến như mẫu Hộp tìm kiếm đang hoạt động. Với ví dụ này ở đây , bạn có thể thấy các thuộc tính ở trên đang hoạt động.

Thăm dò ý kiến ​​với htmx-triggerthuộc tính

Sử dụng thuộc tính kích hoạt HTMX, chúng tôi cũng có thể chỉ định rằng phần tử sẽ thăm dò URL nhất định mỗi ngiây thay vì đợi một sự kiện xảy ra.

<script src="https://unpkg.com/htmx.org@1.7.0"></script>

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s">
      Load Jokes
</div>

Tại đây, HTMX hướng dẫn trình duyệt gửi yêu cầu GET đến /V2.jokeapiURL sau mỗi 3 giây và hiển thị phản hồi trong phần tử div.

Thăm dò ý kiến ​​với HTMX

CodePen-Link

Yêu cầu chỉ báo

Vì trình duyệt không cung cấp phản hồi nên việc thông báo cho người dùng rằng điều gì đó đang xảy ra sẽ rất hữu ích. Bạn có thể làm điều này với HTMX bằng cách sử dụng lớp 'htmx-indicator'.

<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >
 <button>Load Jokes</button>
 <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif">
</div>

Lớp 'htmx-indicator' sẽ đặt độ mờ của bất kỳ phần tử nào có lớp này 0theo mặc định, làm cho nó ẩn nhưng vẫn hiện diện trong DOM. Khi bạn nhấp vào nút 'tải trò đùa', nó sẽ thêm lớp 'htmx-request', hiển thị chỉ báo trình tải.

Yêu cầu-Chỉ báo

CodePen-Link

Các yếu tố nhắm mục tiêu

Như đã nêu trước đây, HTMX tải phản hồi cho một yêu cầu AJAX vào phần tử khởi tạo yêu cầu. Thuộc tính 'hx-target' cho phép bạn tải phản hồi trong một phần tử khác với phần tử đã khởi tạo yêu cầu. 'Hx-target' sẽ chấp nhận bộ chọn CSS và sẽ tự động tải phản hồi AJAX vào phần tử đích:

<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes
 
</button>
<div class= "jokes" id="result"></div>

Trong bản demo ở trên, khi bạn nhấp vào load jokesnút, nó sẽ tự động tải phản hồi vào divphần tử bên dưới nó.

htmx_target

CodePen-Link

Hoán đổi

Giống như hx-targettrong phần trước, HTMX cung cấp một cách khác để xác định cách tải phản hồi được trả về bởi Ajax trong Dom. Bạn có thể làm như vậy bằng cách đặt thuộc tính 'hx-swap' với bất kỳ giá trị nào được liệt kê bên dưới:

  • innerHTML: Đây là giá trị mặc định; nó chèn nội dung vào phần tử đích gửi yêu cầu. outerHTML: Nó thay thế toàn bộ phần tử đích bằng nội dung trả về.
  • afterbegin: Nó thêm vào trước phản hồi trước phần tử con đầu tiên bên trong phần tử đích.
  • beforebegin: thêm vào trước phản hồi dưới dạng phần tử mẹ của phần tử thực sự kích hoạt yêu cầu.
  • beforeend: Nó thêm phản hồi sau phần tử con cuối cùng của phần tử gửi yêu cầu.
  • afterend: giống như beforeend, điều này thêm phản hồi sau yêu cầu gửi phần tử.
  • none: tùy chọn này không thêm hoặc thêm trước phản hồi từ một yêu cầu AJAX.

Đây là một ví dụ về thanh tiến trình cuộn sử dụng một số thuộc tính được đề cập ở trên ( https://htmx.org/examples/progress-bar ).

Đồng bộ hóa Yêu cầu với HTMX

Đôi khi, bạn sẽ cần phải đồng bộ hóa các yêu cầu giữa hai phần tử. Giả sử bạn muốn một yêu cầu từ một phần tử ghi đè các yêu cầu của phần tử khác hoặc bạn muốn đợi cho đến khi các yêu cầu của phần tử khác hoàn tất. Bạn có thể làm điều này bằng cách sử dụng hx-syncthuộc tính. Hãy xem xét đoạn mã dưới đây:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
    >
    <button type="submit">Submit</button>
</form>

Trong ví dụ trên, chúng tôi có một biểu mẫu gửi và một inputyêu cầu xác thực cá nhân. Nếu không sử dụng hx-sync, khi bạn điền và gửi biểu mẫu, nó sẽ kích hoạt đồng thời hai yêu cầu song /changesong /validate. Theo tài liệu, việc sử dụng hx-sync=" closest form:abort" trên đầu vào sẽ theo dõi các yêu cầu trên formvà tạm dừng các yêu cầu đầu vào nếu có yêu cầu biểu mẫu hoặc bắt đầu trong khi yêu cầu đầu vào đang chạy:

<form hx-post="/article">
    <input id="title" name="title" type="text" 
        hx-post="/validate" 
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

Sử dụng cách tiếp cận này, chúng tôi có thể khắc phục sự cố đồng bộ hóa giữa hai phần tử một cách khai báo. Bạn có thể đọc thêm về hx-syncthuộc tính tại đây .

Tải lên tệp bằng HTMX

Với HTMX, bạn có thể tạo một biểu mẫu tải lên tệp sẽ được gửi qua Ajax tới phần phụ trợ của bạn để xử lý. Bạn có thể dễ dàng gửi các tệp như video, hình ảnh và tài liệu. Bạn có thể triển khai điều này với HTMX bằng cách nhúng trực tiếp các hx-encodingthuộc tính có giá trị multipart/form-datavào phần tử mẹ gửi yêu cầu:

<form hx-encoding='multipart/form-data' hx-post='/registration'
          _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
        <input type='file' name='userFile'>
        <button>
            Upload File
        </button>
   </form>

Xác thực đầu vào với HTMX

Htmx kết hợp nguyên bản với API xác thực HTML 5, vì vậy nếu đầu vào có thể xác thực không hợp lệ, nó sẽ không gửi yêu cầu. Tính năng này áp dụng cho cả yêu cầu AJAX và gửi WebSockets. Ngoài ra, HTMX kích hoạt các sự kiện xung quanh xác thực mà bạn có thể sử dụng để kết nối xác thực tùy chỉnh và xử lý lỗi. Các sự kiện sau hiện có sẵn:

  • `htmx: validation: validate - được sử dụng để thêm logic xác thực tùy chỉnh.
  • htmx: validation: fail` - sự kiện này kích hoạt khi xác thực phần tử trả về false, ví dụ: cho biết đầu vào không hợp lệ.
  • htmx:validation: halted: Nó gọi sự kiện này khi bạn yêu cầu không được đưa ra do lỗi xác thực. Bạn có thể tìm thấy các lỗi cụ thể trong event.detail.errorsđối tượng.

Hãy xem xét một đầu vào sử dụng htmx:validate:validatesự kiện để đảm bảo rằng đầu vào có giá trị Davidbằng cách sử dụng hyperscript :

<form hx-post="/validate">
 <input _="on htmx:validation:validate
 if my.value != 'David'
 call me.setCustomValidity('Please enter the value David')
 else
 call me.setCustomValidity('')"
 name="username"
 >
</form>

Điều quan trọng cần lưu ý là tất cả xác thực phía máy khách phải xảy ra trên máy chủ, vì nó luôn có thể bị bỏ qua.

Hoạt ảnh CSS với HTMX

Htmx cho phép bạn sử dụng các chuyển tiếp CSS để thêm các hoạt ảnh và chuyển tiếp mượt mà vào trang web của bạn chỉ bằng CSS và HTML mà không sử dụng JavaScript. HTMX cung cấp một phần mở rộng hoạt ảnh mạnh mẽ được gọi là class-toolscho phép bạn xác định các lớp CSS hoán đổi vào hoặc tắt phần tử bằng cách sử dụng thuộc tính classeshoặc data-classes.

Bạn có thể sử dụng tiện ích mở rộng bằng cách gán classesthuộc tính cho một phần tử. Giá classestrị thuộc tính bao gồm các “lần chạy” được phân tách bằng ký tự &. Trong một lần chạy, nó sẽ áp dụng tuần tự các hoạt động của lớp với độ trễ được chỉ định. Các hoạt động của lớp này add, removehoặc toggleđi kèm với tên lớp CSS và tùy chọn bằng dấu hai chấm: và độ trễ thời gian.

<div classes= “add sample-demo: 1s”></div>

Sau khi tải nội dung trình duyệt, HTMX sẽ tự động thêm một lớp mới sample-demovào div sau 1 giây. Hãy xem ví dụ demo này bên dưới:

<div hx-ext="class-tools">
 <div class="demo" classes="toggle faded:1s">See me Fading Away </div>

</div>

htmx_transition

CodePen-Link Bạn có thể tìm hiểu thêm về cách tạo hoạt ảnh và chuyển tiếp hấp dẫn với HTMX tại đây .

HTMX tích hợp liền mạch với các khuôn khổ phía máy chủ khác nhau, mặc dù một số khuôn khổ có thể có các lựa chọn thay thế để cài đặt HTMX. Hãy xem liên kết này để khám phá cách bạn có thể tích hợp HTMX với các khuôn khổ phía máy chủ khác nhau.

Sự kết luận

HTMX là một công nghệ đáng kinh ngạc và tôi rất hào hứng với nó cũng như không thể chờ đợi để sử dụng nó trong quá trình sản xuất trong dự án tiếp theo của mình. Trong hướng dẫn này, chúng tôi đã khám phá cách cài đặt HTMX, gửi yêu cầu Ajax, tải tệp lên, xác thực đầu vào và tạo chuyển tiếp CSS mà không cần sử dụng javaScript ở phía máy khách.

Kiểm tra liên kết này để khám phá một số bộ demo mẫu UX được triển khai với HTMX mà bạn có thể chỉnh sửa và tích hợp với các dự án của mình.

Liên kết sau ( https://htmx.org/examples/ ) chứa một số bộ trình diễn mẫu UX mà bạn có thể chỉnh sửa và tích hợp vào các dự án của mình.

Nguồn: https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

HTMX: Cách Tiếp Cận Mới Nhất Cho Các ứng Dụng Web Không Sử Dụng JS

HTMX: The Newest Approach for JavaScript-less Web Apps

According to the documentation, the HTMX library allows you to add modern browser features without using Javascript. It gives you access to CSS Transitions, AJAX, WebSockets, and Server-Sent Events directly in HTML, using attributes to build modern user interfaces quickly. Would it be possible to develop web apps on the client-side without JavaScript? In this tutorial, we will explore all the mind-blowing features of HTMX. You will learn how to send Ajax requests, upload files, validate input, and trigger CSS transitions without writing JavaScript code.

What is HTMX, and why is it important?

In 2013, Carson Gross created an alternative frontend library intercooler.js, with the tagline “Ajax With Attributes” to simplify the complexity of frontend web development. A new version of intercooler.js reached version 2.0 and became htmx described as a library that enables you to access Ajax, WebSockets, CSS transition, and Server-Sent Events directly inside HTML.

See  more at: https://blog.openreplay.com/exploring-htmx-building-dynamic-web-apps-without-javascript

#javascript #htmx 

 HTMX:  The Newest Approach for JavaScript-less Web Apps
Duyen Hoang

Duyen Hoang

1657029720

Cách thiết lập Django với htmx và Tailwind CSS

Trong hướng dẫn này, bạn sẽ học cách thiết lập Django với htmxTailwind CSS . Mục tiêu của cả htmx và Tailwind là đơn giản hóa việc phát triển web hiện đại để bạn có thể thiết kế và kích hoạt tính tương tác mà không bao giờ rời bỏ sự thoải mái và dễ dàng của HTML. Chúng ta cũng sẽ xem xét cách sử dụng Django Compressor để đóng gói và giảm thiểu nội dung tĩnh trong ứng dụng Django.

htmx

htmx là một thư viện cho phép bạn truy cập các tính năng hiện đại của trình duyệt như AJAX, CSS Transitions, WebSockets và Sự kiện do máy chủ gửi trực tiếp từ HTML, thay vì sử dụng JavaScript. Nó cho phép bạn xây dựng giao diện người dùng một cách nhanh chóng trực tiếp trong đánh dấu.

htmx mở rộng một số tính năng đã được tích hợp sẵn trong trình duyệt, như thực hiện các yêu cầu HTTP và phản hồi các sự kiện. Ví dụ: thay vì chỉ có thể thực hiện các yêu cầu GET và POST thông qua aformcác phần tử, bạn có thể sử dụng các thuộc tính HTML để gửi các yêu cầu GET, POST, PUT, PATCH hoặc DELETE trên bất kỳ phần tử HTML nào:

<button hx-delete="/user/1">Delete</button>

Bạn cũng có thể cập nhật các phần của trang để tạo Ứng dụng một trang (SPA): liên kết CodePen

Mở tab mạng trong các công cụ dành cho nhà phát triển của trình duyệt. Khi nút được nhấp, một yêu cầu XHR được gửi đến https://v2.jokeapi.dev/joke/Any?format=txt&safe-modeđiểm cuối. Phản hồi sau đó được thêm vào pphần tử có idđầu ra.

Để biết thêm ví dụ, hãy xem trang Ví dụ về giao diện người dùng từ tài liệu htmx chính thức.

Ưu và nhược điểm

Ưu điểm :

  1. Năng suất của nhà phát triển : Bạn có thể xây dựng giao diện người dùng hiện đại mà không cần chạm vào JavaScript. Để biết thêm về điều này, hãy xem An SPA Alternative .
  2. Đóng gói một cú đấm : Bản thân thư viện nhỏ (~ 10k min.gz'd), không phụ thuộc và có thể mở rộng .

Nhược điểm :

  1. Sự trưởng thành của thư viện : Vì thư viện còn khá mới nên việc triển khai tài liệu và ví dụ rất thưa thớt.
  2. Kích thước dữ liệu được truyền : Thông thường, các khung công tác SPA (như React và Vue) hoạt động bằng cách truyền dữ liệu qua lại giữa máy khách và máy chủ ở định dạng JSON. Dữ liệu nhận được sau đó sẽ được hiển thị bởi máy khách. Mặt khác, htmx nhận HTML được kết xuất từ ​​máy chủ và nó thay thế phần tử đích bằng phản hồi. HTML ở định dạng được hiển thị thường lớn hơn về kích thước so với phản hồi JSON.

CSS Tailwind

Tailwind CSS là một khung CSS "ưu tiên tiện ích". Thay vì vận chuyển các thành phần được xây dựng sẵn (mà các khung công tác như BootstrapBulma chuyên về), nó cung cấp các khối xây dựng dưới dạng các lớp tiện ích cho phép người ta tạo bố cục và thiết kế một cách nhanh chóng và dễ dàng.

Ví dụ: lấy HTML và CSS sau:

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

Điều này có thể được triển khai với Tailwind như sau:

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

Hãy xem Trình chuyển đổi CSS Tailwind để chuyển đổi CSS thô sang các lớp tiện ích tương đương trong Tailwind. So sánh các kết quả.

Ưu và nhược điểm

Ưu điểm :

  1. Khả năng tùy chỉnh cao : Mặc dù Tailwind đi kèm với các lớp được tạo sẵn, nhưng chúng có thể được ghi đè bằng cách sử dụng tệp tailwind.config.js .
  2. Tối ưu hóa : Bạn có thể định cấu hình Tailwind để tối ưu hóa đầu ra CSS bằng cách chỉ tải các lớp thực sự được sử dụng.
  3. Chế độ tối : Thật dễ dàng để thực hiện chế độ tối - ví dụ <div class="bg-white dark:bg-black">:.

Nhược điểm :

  1. Thành phần : Tailwind không cung cấp bất kỳ thành phần chính thức nào được tạo sẵn như nút, thẻ, thanh điều hướng, v.v. Các thành phần phải được tạo ra từ đầu. Có một số tài nguyên do cộng đồng điều khiển cho các thành phần như Thành phần CSS Tailwind và Hộp công cụ Tailwind , có thể kể tên một số tài nguyên. Ngoài ra còn có một thư viện thành phần mạnh mẽ, mặc dù phải trả phí, của các nhà sản xuất Tailwind có tên Tailwind UI .
  2. CSS nội tuyến : Điều này kết hợp nội dung và thiết kế, điều này làm tăng kích thước trang và làm lộn xộn HTML.

Máy nén Django

Django Compressor là một tiện ích mở rộng được thiết kế để quản lý (nén / lưu vào bộ nhớ đệm) nội dung tĩnh trong ứng dụng Django. Với nó, bạn tạo một đường dẫn nội dung đơn giản cho:

  1. Biên dịch SassLESS sang CSS stylesheet
  2. Kết hợp và giảm thiểu nhiều tệp CSS và JavaScript xuống thành một tệp duy nhất cho mỗi tệp
  3. Tạo các gói nội dung để sử dụng trong các mẫu của bạn

Cùng với đó, hãy cùng xem cách làm việc với từng công cụ trên trong Django!

Thiết lập dự án

Để bắt đầu, hãy tạo một thư mục mới cho dự án của chúng tôi, tạo và kích hoạt một môi trường ảo mới và cài đặt Django cùng với Django Compressor:

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

Tiếp theo, hãy cài đặt pytailwindcss và tải xuống tệp nhị phân:

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

Tạo một dự án Django mới và một todosứng dụng:

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

Thêm các ứng dụng vào INSTALLED_APPSdanh sách trong config / settings.py :

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

Tạo một thư mục "mẫu" trong thư mục gốc của dự án của bạn. Sau đó, cập nhật các TEMPLATEScài đặt như sau:

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

Hãy thêm một số cấu hình vào config / settings.py cho compressor:

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

Ghi chú:

  1. COMPRESS_ROOT xác định vị trí tuyệt đối mà từ đó các tệp được nén được đọc và các tệp nén được ghi vào.
  2. COMPRESS_ENABLED boolean để xác định xem quá trình nén có xảy ra hay không. Nó mặc định là giá trị ngược lại của DEBUG.
  3. STATICFILES_FINDERS phải bao gồm công cụ tìm tệp của Django Compressor khi django.contrib.staticfilesđược cài đặt.

Khởi tạo CSS Tailwind trong dự án của bạn:

(venv)$ tailwindcss init

Lệnh này đã tạo một tệp tailwind.config.js trong thư mục gốc của dự án của bạn. Tất cả các tùy chỉnh liên quan đến Tailwind đều có trong tệp này.

Cập nhật tailwind.config.js như sau:

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Ghi chú phần nội dung . Tại đây, bạn định cấu hình đường dẫn đến các mẫu HTML của dự án. Tailwind CSS sẽ quét các mẫu của bạn, tìm kiếm tên lớp Tailwind. Tệp CSS đầu ra được tạo sẽ chỉ chứa CSS cho các tên lớp có liên quan được tìm thấy trong tệp mẫu của bạn. Điều này giúp giữ cho các tệp CSS được tạo nhỏ hơn vì chúng sẽ chỉ chứa các kiểu thực sự đang được sử dụng.

Tiếp theo, trong thư mục gốc của dự án, hãy tạo các tệp và thư mục sau:

static
└── src
    └── main.css

Sau đó, thêm phần sau vào static / src / main.css :

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

Ở đây, chúng tôi đã xác định tất cả basecomponentscác utilitieslớp từ Tailwind CSS.

Đó là nó. Bây giờ bạn có Máy nén Django và Tailwind được kết nối. Tiếp theo, chúng ta sẽ xem xét cách cung cấp tệp index.html để xem CSS đang hoạt động.

Ví dụ đơn giản

Cập nhật tệp todos / views.py như sau:

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

Thêm chế độ xem vào todos / urls.py :

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

Sau đó, thêm todos.urlsvào config / urls.py :

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

Thêm tệp _base.html vào "mẫu":

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

Ghi chú:

  1. {% load compress %}nhập tất cả các thẻ cần thiết để hoạt động với Django Compressor.
  2. {% load static %}tải các tệp tĩnh vào mẫu.
  3. {% compress css %}áp dụng các bộ lọc thích hợp cho tệp static / src / main.css .

Ngoài ra, chúng tôi đã thêm một số màu vào nội dung HTML thông qua <body class="bg-blue-100">. bg-blue-100được sử dụng để thay đổi màu nền thành xanh lam nhạt.

Thêm tệp index.html :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

Bây giờ, hãy chạy lệnh sau trong thư mục gốc của dự án để quét các mẫu cho các lớp và tạo tệp CSS:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Áp dụng di chuyển và chạy máy chủ phát triển:

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Điều hướng đến http: // localhost: 8000 trong trình duyệt của bạn để xem kết quả. Cũng lưu ý về tệp được tạo trong thư mục "static / CACHE / css".

Với Tailwind được định cấu hình, hãy thêm htmx vào hỗn hợp và tạo một tìm kiếm trực tiếp hiển thị kết quả khi bạn nhập.

Ví dụ về Tìm kiếm Trực tiếp

Thay vì tìm nạp thư viện htmx từ CDN, hãy tải xuống và sử dụng Django Compressor để gói nó.

Tải xuống thư viện từ https://unpkg.com/htmx.org@1.7.0/dist/htmx.js và lưu nó vào static / src / htmx.js.

Để chúng tôi có một số dữ liệu để làm việc, hãy lưu https://github.com/testdrivenio/django-htmx-tailwind/blob/master/todos/todo.py vào một tệp mới có tên todos / todo.py.

Bây giờ, hãy thêm chế độ xem để triển khai chức năng tìm kiếm vào todos / views.py :

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

Chúng tôi đã thêm một chế độ xem mới, searchtìm kiếm các việc cần làm và hiển thị mẫu todo.html với tất cả các kết quả.

Thêm dạng xem mới tạo vào todos / urls.py :

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

Tiếp theo, thêm nội dung mới vào tệp _base.html :

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

Chúng tôi đã tải thư viện htmx bằng {% compress js %}thẻ. Theo mặc địnhjs , thẻ được áp dụng (theo đó, áp dụng rjsmin ). Vì vậy, điều này sẽ giảm thiểu static / src / htmx.js và phục vụ nó từ thư mục "static / CACHE".JSMinFilter

Chúng tôi cũng đã thêm tập lệnh sau:

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

Trình nghe sự kiện này thêm mã thông báo CSRF vào tiêu đề yêu cầu.

Tiếp theo, hãy thêm khả năng tìm kiếm dựa trên tiêu đề của từng việc làm.

Cập nhật tệp index.html như sau:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

Hãy dành một chút thời gian để xem xét các thuộc tính được xác định từ htmx:

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. Đầu vào sẽ gửi một yêu cầu POST đến /searchđiểm cuối.
  2. Yêu cầu được kích hoạt thông qua sự kiện keyup với độ trễ 250 mili giây. Vì vậy, nếu một sự kiện keyup mới được nhập trước 250 mili giây trôi qua sau lần keyup cuối cùng, yêu cầu sẽ không được kích hoạt.
  3. Phản hồi HTML từ yêu cầu sau đó được hiển thị trong #todo-resultsphần tử.
  4. Chúng tôi cũng có một chỉ báo, một phần tử tải xuất hiện sau khi yêu cầu được gửi và biến mất sau khi phản hồi trở lại.

Thêm tệp tin mẫu / todo.html :

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

Tệp này hiển thị các việc cần làm phù hợp với truy vấn tìm kiếm của chúng tôi.

Tạo tệp src / output.css mới :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Chạy ứng dụng bằng cách sử dụng python manage.py runservervà điều hướng đến http: // localhost: 8000 một lần nữa để kiểm tra.

thử nghiệm

Sự kết luận

Trong hướng dẫn này, chúng tôi đã xem xét cách:

  • Thiết lập Django Compressor và Tailwind CSS
  • Xây dựng ứng dụng tìm kiếm trực tiếp bằng Django, Tailwind CSS và htmx

htmx có thể hiển thị các phần tử mà không cần tải lại trang. Quan trọng nhất, bạn có thể đạt được điều này mà không cần viết bất kỳ JavaScript nào. Mặc dù điều này làm giảm số lượng công việc cần thiết ở phía máy khách, nhưng dữ liệu được gửi từ máy chủ có thể cao hơn vì nó đang gửi HTML được kết xuất.

Việc cung cấp các mẫu HTML từng phần như thế này đã phổ biến vào đầu những năm 2000. htmx cung cấp một bước ngoặt hiện đại cho cách tiếp cận này. Nói chung, việc cung cấp các mẫu từng phần đang trở nên phổ biến trở lại do các khung công tác phức tạp như React và Vue. Bạn cũng có thể thêm WebSockets vào hỗn hợp để cung cấp các thay đổi theo thời gian thực. Phương pháp tương tự này được sử dụng bởi Phoenix LiveView nổi tiếng . Bạn có thể đọc thêm về HTML qua WebSockets trong Tương lai của Phần mềm Web là HTML-over-WebSocketsHTML Over WebSockets .

Thư viện vẫn còn non trẻ, nhưng tương lai có vẻ rất tươi sáng.

Tailwind là một khung CSS mạnh mẽ tập trung vào năng suất của nhà phát triển. Mặc dù hướng dẫn này không liên quan đến nó, nhưng Tailwind có thể tùy chỉnh cao.

Khi sử dụng Django, hãy đảm bảo kết hợp cả htmx và Tailwind với Django Compressor để đơn giản hóa việc quản lý tài sản tĩnh.

Bạn có thể tìm thấy mã đầy đủ trong kho lưu trữ django-htmx-tailwind .

Nguồn:  https://testdriven.io

#django #htmx #tailwindcss 

Cách thiết lập Django với htmx và Tailwind CSS

Как настроить Django с помощью htmx и Tailwind CSS

В этом руководстве вы узнаете, как настроить Django с помощью htmx и Tailwind CSS . Цель как htmx, так и Tailwind — упростить современную веб-разработку, чтобы вы могли проектировать и обеспечивать интерактивность, не отказываясь от удобства и простоты HTML. Мы также рассмотрим, как использовать Django Compressor для объединения и минимизации статических ресурсов в приложении Django.

htmx

htmx — это библиотека, которая позволяет вам получать доступ к современным функциям браузера, таким как AJAX, переходы CSS, WebSockets и события, отправленные сервером, непосредственно из HTML, а не с помощью JavaScript. Он позволяет быстро создавать пользовательские интерфейсы непосредственно в разметке.

htmx расширяет несколько функций, уже встроенных в браузер, таких как выполнение HTTP-запросов и реагирование на события. Например, вместо того, чтобы делать запросы GET и POST только через элементы aи form, вы можете использовать атрибуты HTML для отправки запросов GET, POST, PUT, PATCH или DELETE для любого элемента HTML:

<button hx-delete="/user/1">Delete</button>

Вы также можете обновить части страницы, чтобы создать одностраничное приложение (SPA): ссылка CodePen

Откройте вкладку сети в инструментах разработчика браузера. При нажатии кнопки на конечную точку отправляется запрос XHR https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode. Затем ответ добавляется к pэлементу с idвыводом.

Дополнительные примеры см . на странице примеров пользовательского интерфейса в официальной документации htmx.

Плюсы и минусы

Плюсы :

  1. Продуктивность разработчиков : вы можете создавать современные пользовательские интерфейсы, не затрагивая JavaScript. Чтобы узнать больше об этом, ознакомьтесь с альтернативой SPA .
  2. Упаковывает удар : сама библиотека небольшая (~ 10 000 мин. gz'd), свободная от зависимостей и расширяемая .

Минусы :

  1. Зрелость библиотеки : Поскольку библиотека довольно новая, документация и примеры реализации скудны.
  2. Размер передаваемых данных . Как правило, фреймворки SPA (например, React и Vue) работают, передавая данные между клиентом и сервером в формате JSON. Полученные данные затем обрабатываются клиентом. htmx, с другой стороны, получает обработанный HTML-код с сервера и заменяет целевой элемент ответом. HTML-код в отображаемом формате обычно больше по размеру, чем ответ JSON.

Попутный ветер CSS

Tailwind CSS — это CSS-фреймворк, ориентированный прежде всего на полезность. Вместо того, чтобы поставлять готовые компоненты (на которых специализируются такие фреймворки, как Bootstrap и Bulma ), он предоставляет строительные блоки в виде служебных классов, которые позволяют быстро и легко создавать макеты и проекты.

Например, возьмите следующий HTML и CSS:

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

Это можно реализовать с помощью Tailwind следующим образом:

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

Воспользуйтесь конвертером CSS Tailwind , чтобы преобразовать необработанный CSS в эквивалентные служебные классы в Tailwind. Сравните результаты.

Плюсы и минусы

Плюсы :

  1. Широкие возможности настройки : хотя Tailwind поставляется с готовыми классами, их можно перезаписать с помощью файла tailwind.config.js .
  2. Оптимизация : вы можете настроить Tailwind для оптимизации вывода CSS, загружая только те классы, которые фактически используются.
  3. Темный режим : реализовать темный режим несложно — например, <div class="bg-white dark:bg-black">.

Минусы :

  1. Компоненты : Tailwind не предоставляет каких-либо официальных готовых компонентов, таких как кнопки, карточки, панели навигации и т. д. Компоненты должны быть созданы с нуля. Существует несколько управляемых сообществом ресурсов для таких компонентов, как Tailwind CSS Components и Tailwind Toolbox , и это лишь некоторые из них. Также есть мощная, хотя и платная, библиотека компонентов от создателей Tailwind под названием Tailwind UI .
  2. Встроенный CSS : он объединяет контент и дизайн, что увеличивает размер страницы и загромождает HTML.

Джанго Компрессор

Django Compressor — это расширение, предназначенное для управления (сжатия/кэширования) статическими ресурсами в приложении Django. С его помощью вы создаете простой конвейер активов для:

  1. Компиляция Sass и LESS в таблицы стилей CSS
  2. Объединение и минимизация нескольких файлов CSS и JavaScript в один файл для каждого
  3. Создание пакетов ресурсов для использования в ваших шаблонах

Итак, давайте посмотрим, как работать с каждым из вышеперечисленных инструментов в Django!

Настройка проекта

Для начала создайте новую папку для нашего проекта, создайте и активируйте новую виртуальную среду и установите Django вместе с Django Compressor:

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

Далее давайте установим pytailwindcss и загрузим его бинарник:

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

Создайте новый проект Django и todosприложение:

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

Добавьте приложения в INSTALLED_APPSсписок в config/settings.py :

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

Создайте папку «templates» в корне вашего проекта. Затем обновите TEMPLATESнастройки следующим образом:

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

Давайте добавим некоторую конфигурацию в config/settings.py для compressor:

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

Заметки:

  1. COMPRESS_ROOT определяет абсолютное местоположение, откуда считываются сжимаемые файлы и куда записываются сжатые файлы.
  2. COMPRESS_ENABLED логическое значение, определяющее, будет ли происходить сжатие. По умолчанию используется значение, противоположное DEBUG.
  3. STATICFILES_FINDERS должен включать средство поиска файлов Django Compressor при django.contrib.staticfilesустановке.

Инициализируйте Tailwind CSS в своем проекте:

(venv)$ tailwindcss init

Эта команда создала файл tailwind.config.js в корне вашего проекта. Все настройки, связанные с Tailwind, находятся в этом файле.

Обновите tailwind.config.js следующим образом:

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Обратите внимание на раздел контента . Здесь вы настраиваете пути к HTML-шаблонам вашего проекта. Tailwind CSS просканирует ваши шаблоны в поисках имен классов Tailwind. Сгенерированный выходной файл CSS будет содержать только CSS для соответствующих имен классов, найденных в ваших файлах шаблонов. Это помогает уменьшить размер сгенерированных файлов CSS, поскольку они будут содержать только те стили, которые фактически используются.

Далее в корне проекта создайте следующие файлы и папки:

static
└── src
    └── main.css

Затем добавьте в static/src/main.css следующее :

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

Здесь мы определили все классы base, componentsи utilitiesиз Tailwind CSS.

Вот и все. Теперь у вас подключены Django Compressor и Tailwind. Далее мы рассмотрим, как обслуживать файл index.html , чтобы увидеть CSS в действии.

Простой пример

Обновите файл todos/views.py следующим образом:

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

Добавьте представление в todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

Затем добавьте todos.urlsв config/urls.py :

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

Добавьте файл _base.html в «шаблоны»:

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

Заметки:

  1. {% load compress %}импортирует все необходимые теги для работы с Django Compressor.
  2. {% load static %}загружает статические файлы в шаблон.
  3. {% compress css %}применяет соответствующие фильтры к файлу static/src/main.css .

Кроме того, мы добавили немного цвета в тело HTML с помощью <body class="bg-blue-100">. bg-blue-100используется для изменения цвета фона на голубой.

Добавьте файл index.html :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

Теперь выполните следующую команду в корне проекта, чтобы отсканировать шаблоны на наличие классов и сгенерировать файл CSS:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Примените миграции и запустите сервер разработки:

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Перейдите по адресу http://localhost:8000 в браузере, чтобы увидеть результаты. Также обратите внимание на сгенерированный файл в папке «static/CACHE/css».

С настроенным Tailwind давайте добавим htmx и создадим живой поиск, который отображает результаты по мере ввода.

Пример живого поиска

Вместо того, чтобы извлекать библиотеку htmx из CDN, давайте загрузим ее и используем Django Compressor для ее сборки.

Загрузите библиотеку с https://unpkg.com/htmx.org@1.7.0/dist/htmx.js и сохраните ее в static/src/htmx.js .

Чтобы у нас были данные для работы, сохраните https://github.com/testdrivenio/django-htmx-tailwind/blob/master/todos/todo.py в новый файл с именем todos/todo.py .

Теперь добавьте представление для реализации функции поиска в todos/views.py :

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

Мы добавили новое представление, searchкоторое ищет задачи и отображает шаблон todo.html со всеми результатами.

Добавьте только что созданное представление в todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

Затем добавьте новый ресурс в файл _base.html :

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

Мы загрузили библиотеку htmx с помощью {% compress js %}тега. Тег jsпо умолчанию применяется JSMinFilter(который, в свою очередь, применяет rjsmin ). Таким образом, это минимизирует static/src/htmx.js и будет обслуживать его из папки «static/CACHE».

Мы также добавили следующий скрипт:

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

Этот прослушиватель событий добавляет токен CSRF в заголовок запроса.

Далее давайте добавим возможность поиска по названию каждой задачи.

Обновите файл index.html следующим образом:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

Давайте рассмотрим атрибуты, определенные в htmx:

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. Вход отправляет запрос POST в /searchконечную точку.
  2. Запрос запускается через событие keyup с задержкой 250 мс. Таким образом, если новое событие нажатия клавиши вводится до истечения 250 мс после последнего нажатия клавиши, запрос не запускается.
  3. Затем HTML-ответ на запрос отображается в #todo-resultsэлементе.
  4. У нас также есть индикатор, элемент загрузки, который появляется после отправки запроса и исчезает после возврата ответа.

Добавьте файл templates/todo.html :

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

Этот файл отображает задачи, соответствующие нашему поисковому запросу.

Создайте новый файл src/output.css :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Запустите приложение с помощью python manage.py runserverи снова перейдите по адресу http://localhost:8000 , чтобы проверить его.

демо

Вывод

В этом уроке мы рассмотрели, как:

  • Настройте Django Compressor и Tailwind CSS
  • Создайте приложение для поиска в реальном времени, используя Django, Tailwind CSS и htmx.

htmx может отображать элементы без перезагрузки страницы. Самое главное, вы можете добиться этого без написания JavaScript. Хотя это уменьшает объем работы, необходимой на стороне клиента, данные, отправляемые с сервера, могут быть выше, поскольку он отправляет обработанный HTML.

Подобные частичные HTML-шаблоны были популярны в начале 2000-х годов. htmx предлагает современный подход к этому подходу. В целом, обслуживание частичных шаблонов снова становится популярным из-за сложности таких фреймворков, как React и Vue. Вы также можете добавить WebSockets для внесения изменений в реальном времени. Этот же подход используется в знаменитом Phoenix LiveView . Вы можете узнать больше о HTML поверх WebSockets в статье Будущее веб-программного обеспечения — это HTML поверх WebSockets и HTML поверх WebSockets .

Библиотека еще молода, но будущее у нее очень светлое.

Tailwind — это мощная CSS-инфраструктура, ориентированная на продуктивность разработчиков. Хотя это руководство не затрагивало этого, Tailwind легко настраивается.

При использовании Django обязательно соедините htmx и Tailwind с Django Compressor, чтобы упростить управление статическими активами.

Полный код можно найти в репозитории django-htmx-tailwind .

Источник:  https://testdriven.io

#django #htmx #tailwindcss 

Как настроить Django с помощью htmx и Tailwind CSS

如何使用 htmx 和 Tailwind CSS 設置 Django

在本教程中,您將學習如何使用htmxTailwind CSS設置 Django 。htmx 和 Tailwind 的目標是簡化現代 Web 開發,以便您可以設計和啟用交互性,而無需離開 HTML 的舒適和易用性。我們還將了解如何使用Django Compressor在 Django 應用程序中捆綁和縮小靜態資源。

htmx

htmx是一個庫,允許您直接從 HTML 訪問現代瀏覽器功能,如 AJAX、CSS 轉換、WebSockets 和服務器發送事件,而不是使用 JavaScript。它允許您直接在標記中快速構建用戶界面。

htmx 擴展了瀏覽器中已經內置的幾個功能,例如發出 HTTP 請求和響應事件。例如,您可以使用 HTML 屬性在任何 HTML 元素上發送 GET、POST、PUT、PATCH 或 DELETE 請求,而不是只能通過a和元素發出 GET 和 POST 請求:form

<button hx-delete="/user/1">Delete</button>

您還可以更新部分頁面以創建單頁應用程序 (SPA):CodePen 鏈接

在瀏覽器的開發工具中打開網絡選項卡。https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode單擊該按鈕時,將向端點發送 XHR 請求。然後將響應附加到p具有idof 輸出的元素。

有關更多示例,請查看官方 htmx 文檔中的UI 示例頁面。

優點和缺點

優點

  1. 開發人員生產力:您無需接觸 JavaScript 即可構建現代用戶界面。有關這方面的更多信息,請查看SPA 替代方案
  2. 打包:庫本身很小(~10k min.gz'd),無依賴且可擴展

缺點

  1. 庫成熟度:由於庫很新,文檔和示例實現很少。
  2. 傳輸的數據大小:通常,SPA 框架(如 React 和 Vue)通過以 JSON 格式在客戶端和服務器之間來回傳遞數據來工作。接收到的數據然後由客戶端呈現。另一方面,htmx 從服務器接收呈現的 HTML,並將目標元素替換為響應。呈現格式的 HTML 在大小方面通常比 JSON 響應大。

順風 CSS

Tailwind CSS是一個“實用程序優先”的 CSS 框架。它沒有提供預先構建的組件(BootstrapBulma等框架專門從事這些組件),而是以實用程序類的形式提供構建塊,使人們能夠快速輕鬆地創建佈局和設計。

例如,採用以下 HTML 和 CSS:

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

這可以使用 Tailwind 來實現,如下所示:

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

查看CSS Tailwind 轉換器,將原始 CSS 轉換為 Tailwind 中的等效實用程序類。比較結果。

優點和缺點

優點

  1. 高度可定制:雖然 Tailwind 帶有預構建的類,但可以使用tailwind.config.js文件覆蓋它們。
  2. 優化:您可以配置Tailwind 以通過僅加載實際使用的類來優化 CSS 輸出。
  3. 暗模式:實現暗模式毫不費力——例如,<div class="bg-white dark:bg-black">.

缺點

  1. 組件:Tailwind 不提供任何官方預構建組件,如按鈕、卡片、導航欄等。組件必須從頭開始創建。Tailwind CSS ComponentsTailwind Toolbox等組件有一些社區驅動的資源,僅舉幾例。Tailwind 的製造商還提供了一個功能強大但已付費的組件庫,稱為Tailwind UI
  2. CSS 是內聯的:這結合了內容和設計,這增加了頁面大小並使 HTML 變得混亂。

Django 壓縮器

Django Compressor是一個擴展,旨在管理(壓縮/緩存)Django 應用程序中的靜態資產。使用它,您可以創建一個簡單的資產管道:

  1. 將SassLESS編譯為 CSS 樣式表
  2. 將多個 CSS 和 JavaScript 文件合併並縮小為每個文件的單個文件
  3. 創建資產包以在您的模板中使用

有了它,讓我們看看如何在 Django 中使用上述每個工具!

項目設置

首先,為我們的項目創建一個新文件夾,創建並激活一個新的虛擬環境,然後安裝 Django 和 Django Compressor:

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

接下來,讓我們安裝pytailwindcss並下載它的二進製文件:

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

創建一個新的 Django 項目和一個todos應用程序:

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

將應用程序添加到config/settings.pyINSTALLED_APPS的列表中:

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

在項目的根目錄中創建一個“模板”文件夾。然後,TEMPLATES像這樣更新設置:

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

讓我們為 config/settings.py 添加一些配置compressor

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

筆記:

  1. COMPRESS_ROOT定義了從其中讀取要壓縮的文件和寫入壓縮文件的絕對位置。
  2. COMPRESS_ENABLED布爾值,用於確定是否會發生壓縮。它默認為 的相反值DEBUG
  3. 安裝時STATICFILES_FINDERS必須包含 Django Compressor 的文件查找器django.contrib.staticfiles

在您的項目中初始化 Tailwind CSS:

(venv)$ tailwindcss init

此命令在項目的根目錄中創建了一個tailwind.config.js文件。所有與 Tailwind 相關的自定義設置都進入此文件。

像這樣更新tai​​lwind.config.js

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

注意內容部分。在這裡,您可以配置項目 HTML 模板的路徑。Tailwind CSS 將掃描您的模板,搜索 Tailwind 類名稱。生成的輸出 CSS 文件將僅包含在您的模板文件中找到的相關類名的 CSS。這有助於保持生成的 CSS 文件較小,因為它們只包含實際使用的樣式。

接下來,在項目根目錄中,創建以下文件和文件夾:

static
└── src
    └── main.css

然後,將以下內容添加到static/src/main.css

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

在這裡,我們定義了 Tailwind CSS 中的所有basecomponentsutilities類。

而已。您現在已經連接了 Django Compressor 和 Tailwind。接下來,我們將看看如何提供一個index.html文件來查看 CSS 的運行情況。

簡單示例

像這樣更新todos/views.py文件:

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

將視圖添加到todos/urls.py

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

然後,添加todos.urlsconfig/urls.py

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

_base.html文件添加到“模板”:

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

筆記:

  1. {% load compress %}導入所有必需的標籤以使用 Django Compressor。
  2. {% load static %}將靜態文件加載到模板中。
  3. {% compress css %}將適當的過濾器應用於static/src/main.css文件。

此外,我們還通過<body class="bg-blue-100">. bg-blue-100用於將背景顏色更改為淺藍色。

添加一個index.html文件:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

現在,在項目的根目錄中運行以下命令以掃描模板中的類並生成 CSS 文件:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

應用遷移並運行開發服務器:

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

在瀏覽器中導航到http://localhost:8000以查看結果。還要記下“static/CACHE/css”文件夾中生成的文件。

配置 Tailwind 後,讓我們將 htmx 添加到組合中並構建一個實時搜索,在您鍵入時顯示結果。

實時搜索示例

與其從 CDN 獲取 htmx 庫,不如下載它並使用 Django Compressor 捆綁它。

從https://unpkg.com/htmx.org@1.7.0/dist/htmx.js下載庫並將其保存到static/src/htmx.js

為了讓我們有一些數據可以使用,請將https://github.com/testdrivenio/django-htmx-tailwind/blob/master/todos/todo.py保存到一個名為todos/todo.py的新文件中。

現在,將實現搜索功能的視圖添加到todos/views.py

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

我們添加了一個新視圖 ,search用於搜索 todos 並使用所有結果呈現todo.html模板。

將新創建的視圖添加到todos/urls.py

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

接下來,將新資產添加到_base.html文件中:

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

我們使用標籤加載了 htmx 庫{% compress js %}默認情況下,該js標籤適用(這反過來又適用rjsmin)。因此,這將縮小static/src/htmx.js並從“static/CACHE”文件夾中提供它。JSMinFilter

我們還添加了以下腳本:

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

此事件偵聽器將 CSRF 令牌添加到請求標頭。

接下來,讓我們添加基於每個待辦事項標題的搜索功能。

像這樣更新index.html文件:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

讓我們花點時間看看從 htmx 定義的屬性:

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. 輸入向/search端點發送 POST 請求。
  2. 該請求是通過延遲 250 毫秒的keyup 事件觸發的。因此,如果在最後一次 keyup 之後的 250 毫秒之前輸入了新的 keyup 事件,則不會觸發請求。
  3. 來自請求的 HTML 響應隨後會顯示在#todo-results元素中。
  4. 我們還有一個指示器,一個加載元素,在請求發送後出現,在響應返回後消失。

添加模板/todo.html文件:

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

此文件呈現與我們的搜索查詢匹配的待辦事項。

生成一個新的src/output.css文件:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

python manage.py runserver使用並再次導航到http://localhost:8000運行應用程序以對其進行測試。

演示

結論

在本教程中,我們研究瞭如何:

  • 設置 Django Compressor 和 Tailwind CSS
  • 使用 Django、Tailwind CSS 和 htmx 構建實時搜索應用程序

htmx 可以在不重新加載頁面的情況下呈現元素。最重要的是,您無需編寫任何 JavaScript 即可實現這一目標。儘管這減少了客戶端所需的工作量,但從服務器發送的數據可能會更高,因為它正在發送呈現的 HTML。

像這樣提供部分 HTML 模板在 2000 年代初期很流行。htmx 為這種方法提供了現代的轉折。一般來說,由於 React 和 Vue 等框架的複雜性,提供部分模板再次變得流行。您也可以將 WebSockets 添加到組合中以提供實時更改。著名的Phoenix LiveView也使用了同樣的方法。您可以在Web 軟件的未來是 HTML-over-WebSocketsHTML Over WebSockets中閱讀更多關於 HTML over WebSockets 的內容。

圖書館還很年輕,但未來看起來很光明。

Tailwind 是一個強大的 CSS 框架,專注於開發人員的生產力。儘管本教程沒有涉及它,但 Tailwind 是高度可定制的。

使用 Django 時,請務必將 htmx 和 Tailwind 與 Django Compressor 耦合以簡化靜態資產管理。

完整的代碼可以在django-htmx-tailwind存儲庫中找到。

來源:  https ://testdriven.io

#django #htmx #tailwindcss 

如何使用 htmx 和 Tailwind CSS 設置 Django
Noelia  Graham

Noelia Graham

1657007820

Comment configurer Django avec htmx et Tailwind CSS

Dans ce didacticiel, vous apprendrez à configurer Django avec htmx et Tailwind CSS . L'objectif de htmx et de Tailwind est de simplifier le développement Web moderne afin que vous puissiez concevoir et activer l'interactivité sans jamais quitter le confort et la facilité du HTML. Nous verrons également comment utiliser Django Compressor pour regrouper et minimiser les actifs statiques dans une application Django.

htmx

htmx est une bibliothèque qui vous permet d'accéder à des fonctionnalités de navigateur modernes telles que AJAX, CSS Transitions, WebSockets et Server-Sent Events directement à partir de HTML, plutôt que d'utiliser JavaScript. Il vous permet de créer rapidement des interfaces utilisateur directement dans le balisage.

htmx étend plusieurs fonctionnalités déjà intégrées au navigateur, telles que les requêtes HTTP et la réponse aux événements. Par exemple, plutôt que de pouvoir uniquement effectuer des requêtes GET et POST via des éléments aet form, vous pouvez utiliser des attributs HTML pour envoyer des requêtes GET, POST, PUT, PATCH ou DELETE sur n'importe quel élément HTML :

<button hx-delete="/user/1">Delete</button>

Vous pouvez également mettre à jour des parties d'une page pour créer une application monopage (SPA) : lien CodePen

Ouvrez l'onglet réseau dans les outils de développement du navigateur. Lorsque le bouton est cliqué, une demande XHR est envoyée au point de https://v2.jokeapi.dev/joke/Any?format=txt&safe-modeterminaison. La réponse est ensuite ajoutée à l' pélément avec une idsortie of.

Pour plus d'exemples, consultez la page Exemples d'interface utilisateur de la documentation officielle htmx.

Avantages et inconvénients

Avantages :

  1. Productivité des développeurs : Vous pouvez créer des interfaces utilisateur modernes sans toucher à JavaScript. Pour en savoir plus, consultez An SPA Alternative .
  2. Emballe un coup de poing : la bibliothèque elle-même est petite (~ 10k min.gz'd), sans dépendance et extensible .

Inconvénients :

  1. Maturité de la bibliothèque : Étant donné que la bibliothèque est assez récente, la documentation et les exemples d'implémentation sont rares.
  2. Taille des données transférées : Typiquement, les frameworks SPA (comme React et Vue) fonctionnent en faisant passer des données entre le client et le serveur au format JSON. Les données reçues sont ensuite restituées par le client. htmx, d'autre part, reçoit le rendu HTML du serveur et remplace l'élément cible par la réponse. Le HTML au format rendu est généralement plus grand en termes de taille qu'une réponse JSON.

CSS vent arrière

Tailwind CSS est un framework CSS "utility-first". Plutôt que d'expédier des composants prédéfinis (dans lesquels se spécialisent des frameworks comme Bootstrap et Bulma ), il fournit des blocs de construction sous la forme de classes utilitaires qui permettent de créer des mises en page et des conceptions rapidement et facilement.

Par exemple, prenez le code HTML et CSS suivant :

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

Cela peut être implémenté avec Tailwind comme ceci :

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

Découvrez le convertisseur CSS Tailwind pour convertir le CSS brut en classes utilitaires équivalentes dans Tailwind. Comparez les résultats.

Avantages et inconvénients

Avantages :

  1. Hautement personnalisable : bien que Tailwind soit fourni avec des classes prédéfinies, elles peuvent être écrasées à l'aide du fichier tailwind.config.js .
  2. Optimisation : vous pouvez configurer Tailwind pour optimiser la sortie CSS en ne chargeant que les classes réellement utilisées.
  3. Mode sombre : il est facile d'implémenter le mode sombre - par exemple, <div class="bg-white dark:bg-black">.

Inconvénients :

  1. Composants : Tailwind ne fournit aucun composant pré-construit officiel comme des boutons, des cartes, des barres de navigation, etc. Les composants doivent être créés à partir de zéro. Il existe quelques ressources communautaires pour des composants tels que Tailwind CSS Components et Tailwind Toolbox , pour n'en nommer que quelques-uns. Il existe également une bibliothèque de composants puissante, bien que payante, créée par les créateurs de Tailwind, appelée Tailwind UI .
  2. Le CSS est en ligne : Cela couple contenu et design, ce qui augmente la taille de la page et encombre le HTML.

Compresseur Django

Django Compressor est une extension conçue pour gérer (compresser/mettre en cache) les actifs statiques dans une application Django. Avec lui, vous créez un pipeline d'actifs simple pour :

  1. Compiler Sass et LESS en feuilles de style CSS
  2. Combiner et réduire plusieurs fichiers CSS et JavaScript jusqu'à un seul fichier pour chacun
  3. Création d'assets bundles à utiliser dans vos modèles

Sur ce, regardons comment travailler avec chacun des outils ci-dessus dans Django !

Configuration du projet

Pour commencer, créez un nouveau dossier pour notre projet, créez et activez un nouvel environnement virtuel et installez Django avec Django Compressor :

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

Ensuite, installons pytailwindcss et téléchargeons son binaire :

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

Créez un nouveau projet Django et une todosapplication :

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

Ajoutez les applications à la INSTALLED_APPSliste dans config/settings.py :

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

Créez un dossier "templates" à la racine de votre projet. Ensuite, mettez à jour les TEMPLATESparamètres comme suit :

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

Ajoutons un peu de configuration à config/settings.py pour compressor:

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

Remarques:

  1. COMPRESS_ROOT définit l'emplacement absolu à partir duquel les fichiers à compresser sont lus et les fichiers compressés sont écrits.
  2. COMPRESS_ENABLED booléen pour déterminer si la compression va se produire. Il prend par défaut la valeur opposée de DEBUG.
  3. STATICFILES_FINDERS doit inclure l'outil de recherche de fichiers de Django Compressor lorsqu'il django.contrib.staticfilesest installé.

Initialisez Tailwind CSS dans votre projet :

(venv)$ tailwindcss init

Cette commande a créé un fichier tailwind.config.js à la racine de votre projet. Toutes les personnalisations liées à Tailwind vont dans ce fichier.

Mettez à jour tailwind.config.js comme suit :

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Prenez note de la section de contenu . Ici, vous configurez les chemins vers les modèles HTML de votre projet. Tailwind CSS analysera vos modèles, recherchant les noms de classe Tailwind. Le fichier CSS de sortie généré contiendra uniquement le CSS pour les noms de classe pertinents trouvés dans vos fichiers de modèle. Cela aide à garder les fichiers CSS générés petits puisqu'ils ne contiendront que les styles qui sont réellement utilisés.

Ensuite, à la racine du projet, créez les fichiers et dossiers suivants :

static
└── src
    └── main.css

Ensuite, ajoutez ce qui suit à static/src/main.css :

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

Ici, nous avons défini toutes les classes base, componentset utilitiesde Tailwind CSS.

C'est ça. Vous avez maintenant Django Compressor et Tailwind câblés. Ensuite, nous verrons comment servir un fichier index.html pour voir le CSS en action.

Exemple simple

Mettez à jour le fichier todos/views.py comme ceci :

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

Ajoutez la vue à todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

Ensuite, ajoutez todos.urlsà config/urls.py :

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

Ajoutez un fichier _base.html à "templates" :

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

Remarques:

  1. {% load compress %}importe toutes les balises requises pour fonctionner avec Django Compressor.
  2. {% load static %}charge les fichiers statiques dans le modèle.
  3. {% compress css %}applique les filtres appropriés au fichier static/src/main.css .

De plus, nous avons ajouté de la couleur au corps HTML via <body class="bg-blue-100">. bg-blue-100est utilisé pour changer la couleur de fond en bleu clair.

Ajoutez un fichier index.html :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

Maintenant, exécutez la commande suivante à la racine du projet pour analyser les modèles de classes et générer un fichier CSS :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Appliquez les migrations et exécutez le serveur de développement :

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Accédez à http://localhost:8000 dans votre navigateur pour voir les résultats. Prenez également note du fichier généré dans le dossier "static/CACHE/css".

Avec Tailwind configuré, ajoutons htmx dans le mélange et créons une recherche en direct qui affiche les résultats au fur et à mesure que vous tapez.

Exemple de recherche en direct

Plutôt que de récupérer la bibliothèque htmx à partir d'un CDN, téléchargeons-la et utilisons Django Compressor pour la regrouper.

Téléchargez la bibliothèque depuis https://unpkg.com/htmx.org@1.7.0/dist/htmx.js et enregistrez-la dans static/src/htmx.js .

Pour que nous ayons des données avec lesquelles travailler, enregistrez https://github.com/testdriveio/django-htmx-tailwind/blob/master/todos/todo.py dans un nouveau fichier appelé todos/todo.py .

Maintenant, ajoutez la vue pour implémenter la fonctionnalité de recherche à todos/views.py :

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

Nous avons ajouté une nouvelle vue, search, qui recherche les tâches et affiche le modèle todo.html avec tous les résultats.

Ajoutez la vue nouvellement créée à todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

Ensuite, ajoutez le nouvel élément au fichier _base.html :

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

Nous avons chargé la bibliothèque htmx en utilisant la {% compress js %}balise. La jsbalise, par défaut , s'applique JSMinFilter(qui, à son tour, applique rjsmin ). Ainsi, cela réduira static/src/htmx.js et le servira à partir du dossier "static/CACHE".

Nous avons également ajouté le script suivant :

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

Cet écouteur d'événement ajoute le jeton CSRF à l'en-tête de la requête.

Ensuite, ajoutons la possibilité de rechercher en fonction du titre de chaque tâche.

Mettez à jour le fichier index.html comme suit :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

Prenons un moment pour examiner les attributs définis à partir de htmx :

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. L'entrée envoie une demande POST au point de /searchterminaison.
  2. La demande est déclenchée via un événement keyup avec un délai de 250 ms. Ainsi, si un nouvel événement de keyup est entré avant que 250 ms ne se soient écoulés après le dernier keyup, la demande n'est pas déclenchée.
  3. La réponse HTML de la requête est alors affichée dans l' #todo-resultsélément.
  4. Nous avons également un indicateur, un élément de chargement qui apparaît après l'envoi de la requête et disparaît après le retour de la réponse.

Ajoutez le fichier templates/todo.html :

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

Ce fichier affiche les tâches qui correspondent à notre requête de recherche.

Générez un nouveau fichier src/output.css :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Exécutez l'application à l'aide python manage.py runserverde et accédez à nouveau à http://localhost:8000 pour la tester.

démo

Conclusion

Dans ce tutoriel, nous avons vu comment :

  • Configurer Django Compressor et Tailwind CSS
  • Créez une application de recherche en direct à l'aide de Django, Tailwind CSS et htmx

htmx peut afficher des éléments sans recharger la page. Plus important encore, vous pouvez y parvenir sans écrire de code JavaScript. Bien que cela réduise la quantité de travail requise côté client, les données envoyées depuis le serveur peuvent être plus élevées car il envoie du HTML rendu.

Servir des modèles HTML partiels comme celui-ci était populaire au début des années 2000. htmx apporte une touche moderne à cette approche. En général, la diffusion de modèles partiels redevient populaire en raison de la complexité des frameworks tels que React et Vue. Vous pouvez ajouter WebSockets dans le mix pour apporter également des modifications en temps réel. Cette même approche est utilisée par le célèbre Phoenix LiveView . Vous pouvez en savoir plus sur HTML over WebSockets dans The Future of Web Software Is HTML-over-WebSockets and HTML Over WebSockets .

La bibliothèque est encore jeune, mais l'avenir s'annonce très prometteur.

Tailwind est un framework CSS puissant qui se concentre sur la productivité des développeurs. Bien que ce didacticiel n'en ait pas parlé, Tailwind est hautement personnalisable.

Lorsque vous utilisez Django, assurez-vous de coupler à la fois htmx et Tailwind avec Django Compressor pour simplifier la gestion des ressources statiques.

Le code complet se trouve dans le dépôt django-htmx-tailwind .

Source :  https://testdrive.io

#django #htmx #tailwindcss 

Comment configurer Django avec htmx et Tailwind CSS

How to Set Up Django with htmx and Tailwind CSS

In this tutorial, you'll learn how to set up Django with htmx and Tailwind CSS. The goal of both htmx and Tailwind is to simplify modern web development so you can design and enable interactivity without ever leaving the comfort and ease of HTML. We'll also look at how to use Django Compressor to bundle and minify static assets in a Django app.

Source: https://testdriven.io

#django #htmx #tailwindcss 

How to Set Up Django with htmx and Tailwind CSS

Cómo configurar Django con htmx y Tailwind CSS

En este tutorial, aprenderá cómo configurar Django con htmx y Tailwind CSS . El objetivo de htmx y Tailwind es simplificar el desarrollo web moderno para que pueda diseñar y habilitar la interactividad sin dejar nunca la comodidad y la facilidad de HTML. También veremos cómo usar Django Compressor para agrupar y minimizar activos estáticos en una aplicación de Django.

htmlx

htmx es una biblioteca que le permite acceder a funciones de navegador modernas como AJAX, CSS Transitions, WebSockets y Server-Sent Events directamente desde HTML, en lugar de usar JavaScript. Le permite crear interfaces de usuario rápidamente directamente en el marcado.

htmx amplía varias funciones ya integradas en el navegador, como realizar solicitudes HTTP y responder a eventos. Por ejemplo, en lugar de solo poder realizar solicitudes GET y POST a través de elementos ay form, puede usar atributos HTML para enviar solicitudes GET, POST, PUT, PATCH o DELETE en cualquier elemento HTML:

<button hx-delete="/user/1">Delete</button>

También puede actualizar partes de una página para crear una aplicación de página única (SPA): enlace CodePen

Abra la pestaña de red en las herramientas de desarrollo del navegador. Cuando se hace clic en el botón, se envía una solicitud XHR al https://v2.jokeapi.dev/joke/Any?format=txt&safe-modepunto final. Luego, la respuesta se agrega al pelemento con un idde salida.

Para obtener más ejemplos, consulte la página de ejemplos de interfaz de usuario de los documentos oficiales de htmx.

Pros y contras

Ventajas :

  1. Productividad del desarrollador : puede crear interfaces de usuario modernas sin tocar JavaScript. Para obtener más información sobre esto, consulte Una alternativa de SPA .
  2. Tiene un gran impacto: la biblioteca en sí es pequeña (~10k min.gz'd ), libre de dependencias y extensible .

Contras :

  1. Madurez de la biblioteca: dado que la biblioteca es bastante nueva, la documentación y las implementaciones de ejemplo son escasas.
  2. Tamaño de los datos transferidos : por lo general, los marcos SPA (como React y Vue) funcionan pasando datos entre el cliente y el servidor en formato JSON. Los datos recibidos luego son procesados ​​por el cliente. htmx, por otro lado, recibe el HTML renderizado del servidor y reemplaza el elemento de destino con la respuesta. El HTML en formato renderizado suele ser más grande en términos de tamaño que una respuesta JSON.

CSS viento de cola

Tailwind CSS es un marco CSS de "utilidad primero". En lugar de enviar componentes preconstruidos (en los que se especializan marcos como Bootstrap y Bulma ), proporciona bloques de construcción en forma de clases de utilidad que permiten crear diseños y diseños de forma rápida y sencilla.

Por ejemplo, tome el siguiente HTML y CSS:

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

Esto se puede implementar con Tailwind así:

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

Consulte el convertidor CSS Tailwind para convertir CSS sin formato en las clases de utilidad equivalentes en Tailwind. Compara los resultados.

Pros y contras

Ventajas :

  1. Altamente personalizable : aunque Tailwind viene con clases prediseñadas, se pueden sobrescribir con el archivo tailwind.config.js .
  2. Optimización : puede configurar Tailwind para optimizar la salida de CSS cargando solo las clases que realmente se utilizan.
  3. Modo oscuro : es fácil implementar el modo oscuro , por ejemplo, <div class="bg-white dark:bg-black">.

Contras :

  1. Componentes : Tailwind no proporciona ningún componente prediseñado oficial como botones, tarjetas, barras de navegación, etc. Los componentes tienen que ser creados desde cero. Hay algunos recursos impulsados ​​por la comunidad para componentes como Tailwind CSS Components y Tailwind Toolbox , por nombrar algunos. También hay una biblioteca de componentes poderosa, aunque paga, de los creadores de Tailwind llamada Tailwind UI .
  2. CSS está en línea : esto combina contenido y diseño, lo que aumenta el tamaño de la página y desordena el HTML.

Compresor Django

Django Compressor es una extensión diseñada para administrar (comprimir/almacenar en caché) activos estáticos en una aplicación Django. Con él, crea una canalización de activos simple para:

  1. Compilación de hojas de estilo Sass y LESS a CSS
  2. Combinar y minimizar varios archivos CSS y JavaScript en un solo archivo para cada uno
  3. Creación de paquetes de activos para usar en sus plantillas

Con eso, ¡veamos cómo trabajar con cada una de las herramientas anteriores en Django!

Configuración del proyecto

Para comenzar, crea una nueva carpeta para nuestro proyecto, crea y activa un nuevo entorno virtual e instala Django junto con Django Compressor:

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

A continuación, instalemos pytailwindcss y descarguemos su binario:

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

Cree un nuevo proyecto Django y una todosaplicación:

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

Agregue las aplicaciones a la INSTALLED_APPSlista en config/settings.py :

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

Cree una carpeta de "plantillas" en la raíz de su proyecto. Luego, actualice la TEMPLATESconfiguración de esta manera:

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

Agreguemos alguna configuración a config/settings.py para compressor:

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

Notas:

  1. COMPRESS_ROOT define la ubicación absoluta desde donde se leen los archivos que se van a comprimir y donde se escriben los archivos comprimidos.
  2. COMPRESS_ENABLED booleano para determinar si se realizará la compresión. Por defecto es el valor opuesto de DEBUG.
  3. STATICFILES_FINDERS debe incluir el buscador de archivos de Django Compressor cuando django.contrib.staticfilesse instala.

Inicializa Tailwind CSS en tu proyecto:

(venv)$ tailwindcss init

Este comando creó un archivo tailwind.config.js en la raíz de su proyecto. Todas las personalizaciones relacionadas con Tailwind van a este archivo.

Actualice tailwind.config.js así:

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Toma nota de la sección de contenido . Aquí configura las rutas a las plantillas HTML de su proyecto. Tailwind CSS escaneará sus plantillas, buscando nombres de clases de Tailwind. El archivo CSS de salida generado solo contendrá CSS para los nombres de clase relevantes que se encuentran en sus archivos de plantilla. Esto ayuda a mantener pequeños los archivos CSS generados, ya que solo contendrán los estilos que realmente se están utilizando.

A continuación, en la raíz del proyecto, cree los siguientes archivos y carpetas:

static
└── src
    └── main.css

Luego, agregue lo siguiente a static/src/main.css :

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

Aquí, definimos todas las clases base, componentsy utilitiesde Tailwind CSS.

Eso es todo. Ahora tienes Django Compressor y Tailwind conectados. A continuación, veremos cómo publicar un archivo index.html para ver el CSS en acción.

Ejemplo sencillo

Actualice el archivo todos/views.py así:

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

Agregue la vista a todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

Luego, agregue todos.urlsa config/urls.py :

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

Agregue un archivo _base.html a "plantillas":

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

Notas:

  1. {% load compress %}importa todas las etiquetas requeridas para trabajar con Django Compressor.
  2. {% load static %}carga archivos estáticos en la plantilla.
  3. {% compress css %}aplica los filtros apropiados al archivo static/src/main.css .

Además, agregamos algo de color al cuerpo HTML a través de <body class="bg-blue-100">. bg-blue-100se utiliza para cambiar el color de fondo a azul claro.

Agregue un archivo index.html :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

Ahora, ejecute el siguiente comando en la raíz del proyecto para escanear las plantillas en busca de clases y generar un archivo CSS:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Aplique las migraciones y ejecute el servidor de desarrollo:

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Navegue a http://localhost:8000 en su navegador para ver los resultados. También tome nota del archivo generado en la carpeta "static/CACHE/css".

Con Tailwind configurado, agreguemos htmx a la combinación y construyamos una búsqueda en vivo que muestre los resultados a medida que escribe.

Ejemplo de búsqueda en vivo

En lugar de obtener la biblioteca htmx de un CDN, descárguemosla y usemos Django Compressor para agruparla.

Descargue la biblioteca de https://unpkg.com/htmx.org@1.7.0/dist/htmx.js y guárdela en static/src/htmx.js .

Para que tengamos algunos datos con los que trabajar, guarde https://github.com/testdrivenio/django-htmx-tailwind/blob/master/todos/todo.py en un nuevo archivo llamado todos/todo.py .

Ahora, agregue la vista para implementar la función de búsqueda en todos/views.py :

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

Agregamos una nueva vista, search, que busca todos y presenta la plantilla todo.html con todos los resultados.

Agregue la vista recién creada a todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

A continuación, agregue el nuevo activo al archivo _base.html :

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

Cargamos la biblioteca htmx usando la {% compress js %}etiqueta. Se aplica la jsetiqueta, de forma predeterminadaJSMinFilter (que, a su vez, aplica rjsmin ). Entonces, esto minimizará static/src/htmx.js y lo servirá desde la carpeta "static/CACHE".

También agregamos el siguiente script:

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

Este detector de eventos agrega el token CSRF al encabezado de la solicitud.

A continuación, agreguemos la capacidad de buscar según el título de cada tarea pendiente.

Actualice el archivo index.html así:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

Tomemos un momento para ver los atributos definidos desde htmx:

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. La entrada envía una solicitud POST al /searchpunto final.
  2. La solicitud se activa a través de un evento keyup con un retraso de 250 ms. Por lo tanto, si se ingresa un nuevo evento de activación antes de que hayan transcurrido 250 ms después de la última activación, la solicitud no se activa.
  3. La respuesta HTML de la solicitud se muestra en el #todo-resultselemento.
  4. También tenemos un indicador, un elemento de carga que aparece después de que se envía la solicitud y desaparece después de que regresa la respuesta.

Agrega el archivo templates/todo.html :

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

Este archivo muestra todos los que coinciden con nuestra consulta de búsqueda.

Genere un nuevo archivo src/output.css :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Ejecute la aplicación usando python manage.py runservery navegue hasta http://localhost:8000 nuevamente para probarla.

manifestación

Conclusión

En este tutorial, vimos cómo:

  • Configurar Django Compressor y Tailwind CSS
  • Cree una aplicación de búsqueda en vivo usando Django, Tailwind CSS y htmx

htmx puede representar elementos sin recargar la página. Lo más importante es que puede lograr esto sin escribir JavaScript. Aunque esto reduce la cantidad de trabajo requerido en el lado del cliente, los datos enviados desde el servidor pueden ser más altos ya que está enviando HTML renderizado.

Ofrecer plantillas HTML parciales como esta fue popular a principios de la década de 2000. htmx proporciona un giro moderno a este enfoque. En general, ofrecer plantillas parciales se está volviendo popular nuevamente debido a la complejidad de los marcos como React y Vue. Puede agregar WebSockets a la mezcla para ofrecer cambios en tiempo real también. Este mismo enfoque es utilizado por el famoso Phoenix LiveView . Puede leer más sobre HTML sobre WebSockets en El futuro del software web es HTML sobre WebSockets y HTML sobre WebSockets .

La biblioteca aún es joven, pero el futuro parece muy brillante.

Tailwind es un poderoso marco CSS que se enfoca en la productividad del desarrollador. Aunque este tutorial no lo abordó, Tailwind es altamente personalizable.

Cuando utilice Django, asegúrese de acoplar htmx y Tailwind con Django Compressor para simplificar la gestión de activos estáticos.

El código completo se puede encontrar en el repositorio django-htmx-tailwind .

Fuente:  https://testdriven.io

#django #htmx #tailwindcss 

Cómo configurar Django con htmx y Tailwind CSS
Neil  Morgan

Neil Morgan

1656989520

Como Configurar o Django com htmx e Tailwind CSS

Neste tutorial, você aprenderá como configurar o Django com htmx e Tailwind CSS . O objetivo do htmx e do Tailwind é simplificar o desenvolvimento web moderno para que você possa projetar e permitir a interatividade sem nunca deixar o conforto e a facilidade do HTML. Também veremos como usar o Django Compressor para agrupar e reduzir ativos estáticos em um aplicativo Django.

htmx

htmx é uma biblioteca que permite acessar recursos modernos do navegador como AJAX, transições CSS, WebSockets e eventos enviados pelo servidor diretamente do HTML, em vez de usar JavaScript. Ele permite que você construa interfaces de usuário rapidamente diretamente na marcação.

htmx estende vários recursos já embutidos no navegador, como fazer solicitações HTTP e responder a eventos. Por exemplo, em vez de apenas poder fazer solicitações GET e POST por meio ade elementos e form, você pode usar atributos HTML para enviar solicitações GET, POST, PUT, PATCH ou DELETE em qualquer elemento HTML:

<button hx-delete="/user/1">Delete</button>

Você também pode atualizar partes de uma página para criar um aplicativo de página única (SPA): link CodePen

Abra a guia de rede nas ferramentas de desenvolvimento do navegador. Quando o botão é clicado, uma solicitação XHR é enviada ao https://v2.jokeapi.dev/joke/Any?format=txt&safe-modeterminal. A resposta é então anexada ao pelemento com uma idsaída.

Para obter mais exemplos, confira a página de exemplos de interface do usuário dos documentos htmx oficiais.

Prós e contras

Prós :

  1. Produtividade do desenvolvedor : você pode criar interfaces de usuário modernas sem tocar em JavaScript. Para saber mais sobre isso, confira An SPA Alternative .
  2. Um soco : A biblioteca em si é pequena (~10k min.gz'd), livre de dependências e extensível .

Contras :

  1. Maturidade da biblioteca: Como a biblioteca é bastante nova, a documentação e as implementações de exemplo são escassas.
  2. Tamanho dos dados transferidos : Normalmente, as estruturas SPA (como React e Vue) funcionam passando dados entre o cliente e o servidor no formato JSON. Os dados recebidos são então processados ​​pelo cliente. htmx, por outro lado, recebe o HTML renderizado do servidor e substitui o elemento de destino pela resposta. O HTML no formato renderizado geralmente é maior em termos de tamanho do que uma resposta JSON.

Tailwind CSS

Tailwind CSS é um framework CSS "utilitário em primeiro lugar". Em vez de enviar componentes pré-construídos (nos quais frameworks como Bootstrap e Bulma se especializam), ele fornece blocos de construção na forma de classes de utilitários que permitem criar layouts e designs de maneira rápida e fácil.

Por exemplo, pegue o seguinte HTML e CSS:

<style>
.hello {
  height: 5px;
  width: 10px;
  background: gray;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px;
}
</style>

<div class="hello">Hello World</div>

Isso pode ser implementado com o Tailwind assim:

<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>

Confira o CSS Tailwind Converter para converter CSS bruto nas classes de utilitário equivalentes no Tailwind. Compare os resultados.

Prós e contras

Prós :

  1. Altamente personalizável : embora o Tailwind venha com classes pré-criadas, elas podem ser substituídas usando o arquivo tailwind.config.js .
  2. Otimização : Você pode configurar o Tailwind para otimizar a saída CSS carregando apenas as classes que são realmente usadas.
  3. Modo escuro : é fácil implementar o modo escuro - por exemplo, <div class="bg-white dark:bg-black">.

Contras :

  1. Componentes : O Tailwind não fornece nenhum componente oficial pré-construído, como botões, cartões, barras de navegação e assim por diante. Os componentes devem ser criados do zero. Existem alguns recursos orientados pela comunidade para componentes como Tailwind CSS Components e Tailwind Toolbox , para citar alguns. Há também uma biblioteca de componentes poderosa, embora paga, dos criadores do Tailwind chamada Tailwind UI .
  2. CSS é inline : combina conteúdo e design, o que aumenta o tamanho da página e desordena o HTML.

Compressor Django

O Django Compressor é uma extensão projetada para gerenciar (compactar/armazenar em cache) ativos estáticos em um aplicativo Django. Com ele, você cria um pipeline de ativos simples para:

  1. Compilando Sass e LESS para folhas de estilo CSS
  2. Combinando e minificando vários arquivos CSS e JavaScript em um único arquivo para cada
  3. Criando pacotes de ativos para uso em seus modelos

Com isso, vamos ver como trabalhar com cada uma das ferramentas acima no Django!

Configuração do projeto

Para começar, crie uma nova pasta para o nosso projeto, crie e ative um novo ambiente virtual e instale o Django junto com o Django Compressor:

$ mkdir django-htmx-tailwind && cd django-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==4.0.3 django-compressor==3.1

Em seguida, vamos instalar o pytailwindcss e fazer o download do binário:

(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss

Crie um novo projeto Django e um todosaplicativo:

(venv)$ django-admin startproject config .
(venv)$ python manage.py startapp todos

Adicione os aplicativos à INSTALLED_APPSlista em config/settings.py :

# config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todos',  # new
    'compressor',  # new
]

Crie uma pasta "templates" na raiz do seu projeto. Em seguida, atualize as TEMPLATESconfigurações assim:

# config/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'], # new
        ...
    },
]

Vamos adicionar alguma configuração ao config/settings.py para compressor:

# config/settings.py

COMPRESS_ROOT = BASE_DIR / 'static'

COMPRESS_ENABLED = True

STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',)

Notas:

  1. COMPRESS_ROOT define o local absoluto de onde os arquivos a serem compactados são lidos e os arquivos compactados são gravados.
  2. COMPRESS_ENABLED booleano para determinar se a compactação ocorrerá. O padrão é o valor oposto de DEBUG.
  3. STATICFILES_FINDERS deve incluir o localizador de arquivos do Django Compressor quando django.contrib.staticfilesinstalado.

Inicialize o Tailwind CSS em seu projeto:

(venv)$ tailwindcss init

Este comando criou um arquivo tailwind.config.js na raiz do seu projeto. Todas as personalizações relacionadas ao Tailwind vão para este arquivo.

Atualize tailwind.config.js assim:

module.exports = {
  content: [
    './templates/**/*.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Tome nota da seção de conteúdo . Aqui, você configura os caminhos para os modelos HTML do seu projeto. Tailwind CSS irá escanear seus templates, procurando por nomes de classes Tailwind. O arquivo CSS de saída gerado conterá apenas CSS para os nomes de classe relevantes encontrados em seus arquivos de modelo. Isso ajuda a manter os arquivos CSS gerados pequenos, pois eles conterão apenas os estilos que estão realmente sendo usados.

Em seguida, na raiz do projeto, crie os seguintes arquivos e pastas:

static
└── src
    └── main.css

Em seguida, adicione o seguinte a static/src/main.css :

/* static/src/main.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

Aqui, definimos todas as classes base, componentse utilitiesdo Tailwind CSS.

É isso. Agora você tem o Django Compressor e o Tailwind conectados. Em seguida, veremos como servir um arquivo index.html para ver o CSS em ação.

Exemplo Simples

Atualize o arquivo todos/views.py assim:

# todos/views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

Adicione a visualização a todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index

urlpatterns = [
    path('', index, name='index'),
]

Em seguida, adicione todos.urlsa config/urls.py :

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todos.urls')), # new
]

Adicione um arquivo _base.html a "templates":

<!-- templates/_base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}
  </body>
</html>

Notas:

  1. {% load compress %}importa todas as tags necessárias para trabalhar com o Django Compressor.
  2. {% load static %}carrega arquivos estáticos no modelo.
  3. {% compress css %}aplica os filtros apropriados ao arquivo static/src/main.css .

Além disso, adicionamos algumas cores ao corpo HTML via <body class="bg-blue-100">. bg-blue-100é usado para alterar a cor de fundo para azul claro.

Adicione um arquivo index.html :

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <h1>Hello World</h1>
{% endblock content %}

Agora, execute o seguinte comando na raiz do projeto para verificar os modelos de classes e gerar um arquivo CSS:

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Aplique as migrações e execute o servidor de desenvolvimento:

(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Navegue até http://localhost:8000 em seu navegador para ver os resultados. Anote também o arquivo gerado na pasta "static/CACHE/css".

Com o Tailwind configurado, vamos adicionar htmx à mistura e construir uma pesquisa ao vivo que exibe os resultados conforme você digita.

Exemplo de pesquisa ao vivo

Em vez de buscar a biblioteca htmx de um CDN, vamos baixá-la e usar o Django Compressor para agrupá-la.

Baixe a biblioteca em https://unpkg.com/htmx.org@1.7.0/dist/htmx.js e salve-a em static/src/htmx.js .

Para que tenhamos alguns dados para trabalhar, salve https://github.com/testdrivedio/django-htmx-tailwind/blob/master/todos/todo.py em um novo arquivo chamado todos/todo.py .

Agora, adicione a visualização para implementar a funcionalidade de pesquisa em todos/views.py :

# todos/views.py

from django.shortcuts import render
from django.views.decorators.http import require_http_methods  # new

from .todo import todos  # new


def index(request):
    return render(request, 'index.html', {'todos': []}) # modified


# new
@require_http_methods(['POST'])
def search(request):
    res_todos = []
    search = request.POST['search']
    if len(search) == 0:
        return render(request, 'todo.html', {'todos': []})
    for i in todos:
        if search in i['title']:
            res_todos.append(i)
    return render(request, 'todo.html', {'todos': res_todos})

Adicionamos uma nova visualização, search, que procura por todos e renderiza o template todo.html com todos os resultados.

Adicione a visualização recém-criada a todos/urls.py :

# todos/urls.py

from django.urls import path

from .views import index, search  # modified

urlpatterns = [
    path('', index, name='index'),
    path('search/', search, name='search'),  # new
]

Em seguida, adicione o novo recurso ao arquivo _base.html :

<!-- templates/base.html -->

{% load compress %}
{% load static %}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django + HTMX + Tailwind CSS</title>

    {% compress css %}
      <link rel="stylesheet" href="{% static 'src/output.css' %}">
    {% endcompress %}

  </head>
  <body class="bg-blue-100">
    {% block content %}
    {% endblock content %}

    <!-- new -->
    {% compress js %}
      <script type="text/javascript" src="{% static 'src/htmx.js' %}"></script>
    {% endcompress %}

    <!-- new -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      })
    </script>
  </body>
</html>

Carregamos a biblioteca htmx usando a {% compress js %}tag. A jstag, por padrão , se aplica JSMinFilter(que, por sua vez, aplica rjsmin ). Portanto, isso reduzirá o static/src/htmx.js e o servirá da pasta "static/CACHE".

Também adicionamos o seguinte script:

document.body.addEventListener('htmx:configRequest', (event) => {
  event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})

Este ouvinte de eventos adiciona o token CSRF ao cabeçalho da solicitação.

Em seguida, vamos adicionar a capacidade de pesquisar com base no título de cada tarefa.

Atualize o arquivo index.html assim:

<!-- templates/index.html -->

{% extends "_base.html" %}

{% block content %}
  <div class="w-small w-2/3 mx-auto py-10 text-gray-600">
    <input
      type="text"
      name="search"
      hx-post="/search/"
      hx-trigger="keyup changed delay:250ms"
      hx-indicator=".htmx-indicator"
      hx-target="#todo-results"
      placeholder="Search"
      class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
    >
    <span class="htmx-indicator">Searching...</span>
  </div>
  <table class="border-collapse w-small w-2/3 mx-auto">
    <thead>
      <tr>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
        <th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
      </tr>
    </thead>
    <tbody id="todo-results">
      {% include "todo.html" %}
    </tbody>
  </table>
{% endblock content %}

Vamos dar uma olhada nos atributos definidos de htmx:

<input
  type="text"
  name="search"
  hx-post="/search/"
  hx-trigger="keyup changed delay:250ms"
  hx-indicator=".htmx-indicator"
  hx-target="#todo-results"
  placeholder="Search"
  class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
  1. A entrada envia uma solicitação POST para o /searchterminal.
  2. A solicitação é acionada por meio de um evento keyup com um atraso de 250ms. Portanto, se um novo evento de keyup for inserido antes de decorridos 250ms após a última keyup, a solicitação não será acionada.
  3. A resposta HTML da solicitação é exibida no #todo-resultselemento.
  4. Também temos um indicador, um elemento de carregamento que aparece depois que a solicitação é enviada e desaparece depois que a resposta volta.

Adicione o arquivo templates/todo.html :

<!-- templates/todo.html -->

{% for todo in todos %}
  <tr
    class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.id}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {{todo.title}}
    </td>
    <td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
      {% if todo.completed %}
        <span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
      {% else %}
        <span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
      {% endif %}
    </td>
  </tr>
{% endfor %}

Este arquivo renderiza os todos que correspondem à nossa consulta de pesquisa.

Gere um novo arquivo src/output.css :

(venv)$ tailwindcss -i ./static/src/main.css -o ./static/src/output.css --minify

Execute o aplicativo usando python manage.py runservere navegue até http://localhost:8000 novamente para testá-lo.

demonstração

Conclusão

Neste tutorial, vimos como:

  • Configure o Django Compressor e o Tailwind CSS
  • Crie um aplicativo de pesquisa ao vivo usando Django, Tailwind CSS e htmx

htmx pode renderizar elementos sem recarregar a página. Mais importante, você pode conseguir isso sem escrever nenhum JavaScript. Embora isso reduza a quantidade de trabalho necessária no lado do cliente, os dados enviados do servidor podem ser maiores, pois ele está enviando HTML renderizado.

Servir modelos HTML parciais como esse era popular no início dos anos 2000. htmx fornece um toque moderno a essa abordagem. Em geral, servir templates parciais está se tornando popular novamente devido à complexidade de frameworks como React e Vue. Você pode adicionar WebSockets à mistura para fornecer alterações em tempo real também. Essa mesma abordagem é usada pelo famoso Phoenix LiveView . Você pode ler mais sobre HTML sobre WebSockets em O futuro do software da Web é HTML sobre WebSockets e HTML sobre WebSockets .

A biblioteca ainda é jovem, mas o futuro parece muito brilhante.

Tailwind é um poderoso framework CSS que se concentra na produtividade do desenvolvedor. Embora este tutorial não tenha tocado nisso, o Tailwind é altamente personalizável.

Ao usar o Django, certifique-se de acoplar o htmx e o Tailwind com o Django Compressor para simplificar o gerenciamento de ativos estáticos.

O código completo pode ser encontrado no repositório django-htmx-tailwind .

Fonte:  https://testdrive.io

#django #htmx #tailwindcss 

Como Configurar o Django com htmx e Tailwind CSS