You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We simply destroy the session and return a re-rendered home page.
350
350
351
+
## WHY DO I HAVE TO LOGIN IN AND OUT ALL THE TIME!?
352
+
353
+
When we restart the server in development mode, `npm run dev` we are also, through our session configuration killing the session. Hence we have to log in every time that happens.
354
+
355
+
You can get around this by storing the session in a persistent store, but I have just left that here.
356
+
351
357
## First HTMx attributes
352
358
353
359
And we also got to use our first HTMx attributes; `hx-get` and `hx-target`. Let me give a short introduction, but dive deeper in the next post.
@@ -239,7 +244,7 @@ Then create the form in `views/todo/new.ejs`:
239
244
240
245
We'll soon add in the HTMx attributes.
241
246
242
-
Let's clean up the `main.ejs` and make the main section look like this:
247
+
Let's clean up the `main.ejs`, make it a `<main>`-section, take out the hard-coded data and make the main section look like this:
243
248
244
249
```html
245
250
<mainclass="todo-container">
@@ -252,6 +257,8 @@ Let's clean up the `main.ejs` and make the main section look like this:
252
257
</main>
253
258
```
254
259
260
+
Yes - that's all we need. Later our todo-data will be injected into the `todo-list` using HTMX.
261
+
255
262
Notice the `hx-trigger="load"` that will issue a `HTTP GET` towards `/todo/new` when the div is loaded. That will then lazily load the list.
256
263
257
264
Also notice the `<div id="todo-list">` which will be the place where the todo list is generated.
@@ -278,7 +285,7 @@ Let's set up the form and button to issue the requests in the proper way :
278
285
```
279
286
280
287
* With the help `hx-post`, `hx-target` and `hx-swap` we have told HTMx to post the form (it will automatically pick up all inputs in the form), and add the result to `#todo-list`
281
-
* HTMx has a [rich event system](https://htmx.org/attributes/hx-on/) that we can hook into. Here we are getting called after the request and reset the form.
288
+
* HTMx has a [rich event system](https://htmx.org/attributes/hx-on/) that we can hook into, using various `hx-on`-attributes. Here we using `hx-on::after-request` to get called after the request and reset the form. Yes, using some JavaScript, although we are using HTMx (the framework that promise that you shouldn't write any JavaScript ... sue me).
282
289
283
290
Let's now build the backend that stores the todo in firestore and return a snippet of html to insert in `#todo-list`
284
291
@@ -307,15 +314,15 @@ And the `todo/todo-list-item.ejs` can look like this:
307
314
</div>
308
315
```
309
316
310
-
(I made some styling changes here)
317
+
(I made some styling changes here, that you can steal from the [finished style-sheet](https://github.com/marcusoftnet/htmx-todo-tutorial/blob/main/public/style.css))
311
318
312
319
Perfect we can now create new todo items. AND they get prepended to the list. However, if you reload the page the list is gone.
313
320
314
321
### Lazy load the list of todos
315
322
316
323
That's because we are using HTMx capabilities to dynamically update the list, on the client. However, we have never loaded the list of items from the start (or when the page is reloaded).
317
324
318
-
But we have everything we know to do that. Let's lazily load the list. Here's the backend in `routes/todo.js`:
325
+
But we have everything we need to do that, in place (just about). Let's lazily load the list. Here's the backend in `routes/todo.js`:
@@ -371,7 +378,7 @@ Restart the application and log in and you can now see the different routes bein
371
378
372
379
### Toggle completion
373
380
374
-
Toggle completion will be implemented with a `HTTP PUT` and then I'll just replace the entire `#todo-item`.
381
+
Toggle completion will be implemented with a `HTTP PUT` and then I'll just replace the entire `#todo-item`. Update the `todo-list-item.ejs` to look like this:
The correct way, according to REST principles, to respond to `HTTP DEL` is through `No Content` (status code 200 or 204). I've always wonder about that, but now it makes sense. Let's replace this element itself with the empty response, in effect deleting the the element.
426
+
The correct way, according to REST principles, to respond to `HTTP DEL` is through `No Content` (status code 200 or 204, but I ran into problems returning 204). I've always wonder about that, but now it makes sense. Let's replace this element itself with the empty response, in effect deleting the the element.
418
427
419
428
In the template I also show off the `hx-confirm` that will pop-up a confirmation box.
420
429
@@ -467,6 +476,8 @@ Here's the cleaned up code:
467
476
468
477
Nice! We're getting close to done. Let's make a Edit-feature too.
469
478
479
+
(Again - I added some styling here to better see that the icons are clickable - get your [styles here](https://github.com/marcusoftnet/htmx-todo-tutorial/blob/main/public/style.css))
480
+
470
481
### Edit todo item
471
482
472
483
This is a bit trickier - we need a form to edit the item, and then a way to update the item using a `HTTP PUT`.
The `edit.ejs` file looks different enough from the `new.ejs` to call for a separate file, but it's quite similar:
493
526
494
527
```html
495
528
<formid="new-todo-form">
@@ -504,6 +537,10 @@ And the `edit.ejs` file looks different enough from the `new.ejs` to warren a se
504
537
</form>
505
538
```
506
539
540
+
Here we are making `HTTP PUT` request using `hx-put="/todo/<%= todo.id %>"` and update the information about the item. I did not include the Completion here, as there's a separate function for that.
541
+
542
+
I had a problem here when I used the `id` attribute of the HTML elements. When sending a HTML form back (using in our case `hx-put`) we need to use the `name`-attributes on `<input>` elements. `id` are for using the JavaScript DOM.
543
+
507
544
## Summary
508
545
509
546
That's it for this post. We have built a fully-fledge (albeit missing some error handling and validation, I'm happy to admit) todo application, storing the information in a collection per logged in user.
And now the counters are updated through the events that gets triggered
223
+
And now the counters are updated through the events that gets triggered. See the [end result here](https://github.com/marcusoftnet/htmx-todo-tutorial/blob/main/routes/todo.js).
220
224
221
225
## Summary
222
226
@@ -238,4 +242,4 @@ I learned a lot by writing this series and I hope you found it useful too.
238
242
239
243
I think HTMx is a breath of fresh air for web developers that, like me, have got lost in SPA frameworks and JSON-to-HTML parsing. It brings the pure ideas of the web back to the forefront while still allows me to write websites that only rerenders the part of the application that has changed.
240
244
241
-
[The code is found here in the state that I left it in at the end of this post.](https://github.com/marcusoftnet/htmx-todo-tutorial/tree/406bda133d83410d85c52286f66a4f0124b19e6e)
245
+
[The code is found here in the state that I left it in at the end of this post.](https://github.com/marcusoftnet/htmx-todo-tutorial/tree/406bda133d83410d85c52286f66a4f0124b19e6e). I then did some additional refactorings and the [`main` branch contains these improvements.](https://github.com/marcusoftnet/htmx-todo-tutorial)
0 commit comments