Skip to content

Solving the 7 GUIs tasks in both Angular and HTMX with a Java Spring backend with HTMX side-by-side

License

Notifications You must be signed in to change notification settings

Dima-369/angular-htmx-7-guis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

58 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Angular and HTMX solutions to 7 GUIs

Angular with Tailwind CSS

Live Demo: https://angular-7-guis.netlify.app (note that the HTMX takes about a minute to load in sometimes since the free server at https://render.com sleeps and needs to wake up)

https://github.com/Dima-369/angular-htmx-7-guis/blob/master/screenshots/1.png?raw=true

The 7 GUI tasks are detailed here: https://eugenkiss.github.io/7guis/tasks/

Run via

cd angular && ng serve

Infos

Note that the Angular code assumes that the Java Sprint Boot server runs at http://localhost:10000 - but if it is not running, that’s fine as well; the pure Angular components will still work just fine.

In development, I develop the Angular version first to have the UI going and then I jump into Intellij and code the entire backend solution over there. HTMX is always initiated in this way so that the Angular code has the least information about how the backend’s innards do the work.

<div hx-get="http://localhost:10000/timer-init" hx-trigger="load"></div>

The way I used HTMX for those 7 GUI tasks is not optimal, as each user interactions triggers a network call to the Java backend and returns HTML. The HTMX solutions are generally slower in the millisecond range compared to the pure Angular ones, but the delay is minimal, at least when the server is accessed through localhost.

Timer HTMX solution

It currently polls at just 100ms. Using 30ms looks a lot smoother, but kind of spams the hardware, so it is not used. If WebSockets are implemented with HTMX, this wouldn’t be an issue, I think.

I spend way too much time making sure that the HTMX API calls are only fired when the timer is running, and that they are stopped when the timer has reached its duration. In the user interface, this isn’t even noticeable.

Java backend server for HTMX

The backend uses Spring Boot 3.1.5, Java 17, Gradle, Spring Web, Thymeleaf 3.1.2 and starts on port 10000 when launched. This was created via https://start.spring.io/

It is deployed in the free tier on https://render.com and is accessible under https://java-7-guis.onrender.com/

You can start it on localhost like this:

cd spring-boot && ./gradlew bootRun

Dockerfile

The Dockerfile is provided for deployment. Run it via:

docker build -t 7guis . && docker run --publish 10000:10000 7guis

About Hot Reloading

Apparently I was not able to configure Hot Reload on localhost with the backend server inside Intellij Community Edition, so I coded this Emacs Lisp to setup watchers on file changes and then restart the server manually which works just as well.

(defvar dima-spring-file-notifiers nil
  "A list of file notifiers.")

(defun dima-spring-file-notifier ()
  "Set `dima-spring-file-notifiers' to restar the server on changes."
  (--each dima-spring-file-notifiers
    (file-notify-rm-watch it))
  (setq dima-spring-file-notifiers
        (--map
         (file-notify-add-watch it '(change)
                                (lambda (event)
                                  (when (and
                                         (not (eq 'stopped (cl-second event)))
                                         (not (s-ends-with-p "~" (cl-third event))))
                                    (dima-spring-restart)
                                    (dima-notification-via-hammerspoon
                                     "Restarted for change in" (cl-third event)))))
         (f-directories "~/angular-htmx-7-guis/spring-boot/src/" nil t))))

(defun dima-spring-restart ()
  "Kill a running process and restart if needed."
  (when-let ((b (get-buffer "*~/angular-htmx-7-guis/spring-boot/gradlew bootRun*")))
    (let (kill-buffer-query-functions)
      (kill-buffer b)))
  (let ((default-directory "~/angular-htmx-7-guis/spring-boot/"))
    (dima-async-shell-command
     "~/angular-htmx-7-guis/spring-boot/gradlew bootRun"
     :on-failure (lambda (_)
                   (dima-notification-via-hammerspoon "Java Spring failed")))))

(dima-spring-restart)
(dima-spring-file-notifier)
;; use angular's default port
(dima-firefox-open-links "http://localhost:4200")

TODOs

  • switch to glitch.com for the demo server since render.com takes far too long to wake up the server
  • finish all tasks (4.5 / 7 done) in Angular and HTMX
  • add tests for the non HTMX Components?

About

Solving the 7 GUIs tasks in both Angular and HTMX with a Java Spring backend with HTMX side-by-side

Topics

Resources

License

Stars

Watchers

Forks