[Bese-devel] Temporarily storing form data

Drew Crampsie drewc at tech.coop
Fri Nov 4 01:11:08 UTC 2005


Jan Rychter wrote:
> How would I go about saving form data when clicking on action links?  I
> have a form-element based form and I'd like to provide a link for the
> user to go somewhere else to choose an image, then return to the
> form. Form data should be preserved.

You have two choices really. Fancy Javascript, or use a button instead 
of a link for your image chooser.

Links do not submit forms, so the data is never transfered from the 
browser when the link is clicked, and therfore there is no way to save 
it serverside.

I have done this sort of thing with AJAX (using the dojo toolkit). Just 
send off an async. request when the link is clicked (which submits the 
form) to save the data. To do this, you'd have to know how to create 
actions programmatically :

  (defmacro make-action-url (component action)
   "
There has got to be something like this buried in UCW somewhere,
but here's what i use."
   `(ucw::print-uri-to-string
     (compute-url ,component
      :action-id (ucw::make-new-action (ucw::context.current-frame 
*context*)
		 (lambda ()
		   (arnesi:with-call/cc
		     ,action))))))

and then submit the form to the created action url (this is pretty easy 
to do in dojo).

Eventually of course you tire of doing it manually, and come up with 
monstrosities like this (And spend a hell of a lot of time counting 
backticks):

(defmacro with-ajax ((component) &body args)
   (multiple-value-bind (actions callbacks args output)
       (loop for arg in args
	    if (eql (car arg) :action)
	    nconc (cdr arg) into actions
	    else if (eql (car arg) :callback)
	    collect (cdr arg) into callbacks
	    else if (eql (car arg) :output-to)
	    nconc (cdr arg) into output
	    else
	    nconc arg into args
	    finally (return (values actions callbacks args output)))
       `(js:with-unique-js-names (js-callbacks)
	`(progn
	  (setf ,js-callbacks (array))
	  ,,@(loop for c in callbacks
		   for i upfrom 0
		   collect
		   ``(setf (aref ,js-callbacks ,,i)
		      (lambda () ,,(third c))))
	  (dojo.io.bind
		(create
		 ,@(unless
		    ,(getf args :url)
		    `(:url
		      ,(lol::make-action-url
			,component
			(progn
			  , at actions
			  (call-component nil (output-component self))))))
		 ,@ (unless
			,(getf args :post-content)
		      `(:post-content (+ ,,@(loop for c in callbacks
						  for n upfrom 0
						  nconc `((ucw::make-new-callback
							   (ucw::context.current-frame *context*)
							   (lambda (,(car c))
							     ,(second c)))
							  "="
							  `(encode-u-r-i-component ((aref ,js-callbacks ,,n)))
							  "&")))))
		 ,@ (unless
			,(or (getf args :load) (not output) )
		      `(:load
			(lambda (evt data)
			  (setf (slot-value (document.get-element-by-id ,, at output) 
inner-h-t-m-l) data))))
		 ,,:method "post"
		 ,, at args))))))

Which gets called in monstrosites like this :

(dojo.event.connect
	drop "onDrop"
	(lambda ()
	  (dolist (li list-items)
	    (new (dojo.dnd.*html-drag-source li ,(input-id self))))
	  ,
	  (with-ajax (self)
	    (:action nil)
	    (:callback d (let ((list-order
				(mapcar #'(lambda (x)
					    (parse-integer (subseq x (length (input-id self)))))
					(read-from-string d))))
			   (setf (mewa::instances self) (reorder-list (mewa::instances self) 
list-order)))
		       `(progn
			 (setf my-list "(")
			 (dolist (li list-items)
			   (setf my-list (+ my-list "\"" li.id "\"" " ")))
			 (setf my-list (+ my-list ")"))
			 (return my-list)))
	    (:load `(lambda (x data)
		     (setf (slot-value (document.get-element-by-id ,(input-id self)) 
inner-h-t-m-l) data)
		     (make-sortable ,(input-id self)))))))))))


I suggest using a button... it's much easier. :)

drewc




> 
> --J.
> _______________________________________________
> bese-devel mailing list
> bese-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/bese-devel




More information about the bese-devel mailing list