4
\$\begingroup\$

In the following hunchentoot easy-handler definition:

(define-easy-handler (new-game :uri "/new-game") ()           
  (standard-page (:title "Add a new game"
                 :script (ps
                           (defvar add-form nil)
                           (defun validate-game-name (evt)          
                             (when (= (@ add-form name value) "")
                               (chain evt (prevent-default))
                               (alert "Please enter a name.")))
                           (defun init ()                           
                             (setf add-form (chain document
                                                   (get-element-by-id "addform")))
                             (chain add-form
                                    (add-event-listener "submit"
                                                validate-game-name false)))
                           (setf (chain window onload) init)))
    (:h1 "Add a new game to the chart")
    (:form :action "/game-added" :method "post" :id "addform"
      (:p "What is the name of the game?" (:br)
          (:input :type "text" :name "name" :class "txt"))
      (:p (:input :type "submit" :value "Add" :class "btn")))))

What is the most straightforward and architecturally sensible way to pull out the parenscript (lines 3-15)?

Is it really nothing more than creating a lisp function like so

(define-easy-handler (new-game :uri "/new-game") ()           
  (standard-page (:title "Add a new game"
                 :script (separate-js))   ; <- just call the new fn below here
    (:h1 "Add a new game to the chart")
    (:form :action "/game-added" :method "post" :id "addform"
      (:p "What is the name of the game?" (:br)
          (:input :type "text" :name "name" :class "txt"))
      (:p (:input :type "submit" :value "Add" :class "btn")))))

;; Just pulled out the parenscript into a separate function, super simple:
(defun separate-js ()
  (ps
    (defvar add-form nil)
    (defun validate-game-name (evt)          
     (when (= (@ add-form name value) "")
       (chain evt (prevent-default))
       (alert "Please enter a name.")))
    (defun init ()                           
     (setf add-form (chain document
                           (get-element-by-id "addform")))
     (chain add-form
            (add-event-listener "submit"
                        validate-game-name false)))
    (setf (chain window onload) init)))

It's interesting finding that in lisp we are getting by without models, views, or controllers; just using lisp functions & macros. However, these are important steps and concepts here so I wanted to proceed with caution, hence seeking comment & discussion.

The general context of the question here is how to structure a web application. These are my first baby steps doing this in lisp, in contrast to plenty of experience with a more run of the mill MVC. Hence, any illumination of differences in thinking required would be excellent.

The first code block is from the leanpub book "Lisp for the Web". The second is my own super simple modification of that.

For information: In my opinion the book "Lisp for the Web" seems great so long as you get past the introduction and first few pages, which have terrible sentence structure and seem not to have been proof read before being published. The rest of the book is much better quality! I nearly binned it and am glad I didn't.

\$\endgroup\$
  • \$\begingroup\$ Can you please elaborate a bit more about what this code is suppoed to do. \$\endgroup\$ – πάντα ῥεῖ Nov 17 '19 at 11:39
  • \$\begingroup\$ It seems good to me. I still reason with MVC because we still need a models layer (-> put DB-related code together, and maybe give it its own namespace), we need to validate forms client and server side, etc. \$\endgroup\$ – Ehvince Nov 29 '19 at 12:26
  • \$\begingroup\$ I strongly invite you to test and use the Spinneret templating library instead of cl-who. I found Spinneret much easier to compose stuff with than cl-who, and it has some more neat features (markdown integration, knowing how down we are in the template, etc). Don't miss this list in general: github.com/CodyReichert/… \$\endgroup\$ – Ehvince Nov 29 '19 at 12:27
  • \$\begingroup\$ One framework that blurs even more the lines is Weblocks (which is seeing a rewrite and update those last two years): 40ants.com/weblocks/quickstart.html It is a components, ajax-based, server-side isomorphic web framework, where we don't have to write a line of JS at all. I can't recommend it yet (it's pre-alpha, changing and needs more documentation), but you might love to explore it. \$\endgroup\$ – Ehvince Nov 29 '19 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.