Skip to content

Instantly share code, notes, and snippets.

@bamboospirit
Last active January 1, 2021 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bamboospirit/e6ad95503ec40d2c7649f4aa14ad4979 to your computer and use it in GitHub Desktop.
Save bamboospirit/e6ad95503ec40d2c7649f4aa14ad4979 to your computer and use it in GitHub Desktop.
weblocks update widget from a new thread issue
#|
UPDATE: use a websocket https://github.com/40ants/weblocks-websocket
because the response to the request was already sent so the thread has no way to communicate an update to the browser:
https://github.com/40ants/weblocks/issues/54
How to make the button "Add random task (with (update) called from a different thread)" work? Pressing on it results in this error:
Session was not created for this request!
[Condition of type SIMPLE-ERROR]
|#
(ql:quickload '(:weblocks :weblocks-ui :find-port))
(defpackage todo
(:use #:cl
#:weblocks-ui/form
#:weblocks/html)
(:import-from #:weblocks/widget
#:render
#:update
#:defwidget)
(:import-from #:weblocks/actions
#:make-js-action)
(:import-from #:weblocks/app
#:defapp))
(in-package todo)
(defapp tasks)
(defapp tasks
:prefix "/")
(weblocks/debug:on)
(defparameter *port* 4001)
(defmethod weblocks/session:init ((app tasks))
"Hello world!")
(defwidget task ()
((title
:initarg :title
:accessor title)
(done
:initarg :done
:initform nil
:accessor done)))
(defun make-task (title &key done)
(make-instance 'task :title title :done done))
(defwidget task-list ()
((tasks
:initarg :tasks
:accessor tasks)))
(defmethod render ((task task))
"Render a task."
(with-html
(:span (if (done task)
(with-html
(:s (title task)))
(title task)))))
(defmethod render ((widget task-list))
"Render a list of tasks."
(with-html
(:h1 "Tasks")
(:ul
(loop for task in (tasks widget) do
(:li (render task))))))
(defun make-task-list (&rest rest)
(let ((tasks (loop for title in rest
collect (make-task title))))
(make-instance 'task-list :tasks tasks)))
(defmethod add-task ((task-list task-list) title)
(push (make-task title)
(tasks task-list)))
(defmethod render ((task-list task-list))
(with-html
(:h1 "Tasks")
(:input :type "button" :value "Add random task (normal)" :onclick
(weblocks/actions:make-js-action
(lambda (&rest args)
(add-task task-list (format nil "~A" (random 1001)))
(update task-list))))
(:input :type "button" :value "Add random task (with (update) called from a different thread)" :onclick
(weblocks/actions:make-js-action
(lambda (&rest args )
(add-task task-list (format nil "~A" (random 1001)))
(bt:make-thread
(lambda ()
(weblocks/dependencies:with-collected-dependencies
(sleep 0.5)
(update task-list) ; ERROR: Session was not created for this request!
))))))
(loop for task in (tasks task-list) do
(render task))
(with-html-form (:POST (lambda (&key title &allow-other-keys)
(add-task task-list title)))
(:input :type "text"
:name "title"
:placeholder "Task's title")
(:input :type "submit"
:value "Add"))))
(defparameter *task-list* (make-task-list "Make my first Weblocks app"
"Deploy it somewhere"
"Have a profit"))
(defmethod weblocks/session:init ((app tasks))
(declare (ignorable app))
*task-list*)
(weblocks/debug:reset-latest-session)
;(weblocks/server:start :port *port*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment