[Bese-devel] A field class for multiple select inputs

Marijn Haverbeke marijnh at gmail.com
Wed Jun 7 11:50:21 UTC 2006


Hi,

Following is a field class for select elements that allow you to select more
than one options. Unless I missed something, there is no class yet for
select elements like that. This could be added to components/form.lisp to
implement that. BUT, you'll probably notice the really ugly hack with the
hidden input whose callback grabs all the values for the select input out of
the parameters. If there is a better way to run code when a request is made
I'd like to hear about it, so I can make a prettier implementation.

Maybe the callback mechanism needs some rethinking anyway? The (setf
(client-value field) nil) in the render method of checkbox-field is also a
case of code that should always be run before the parameters are handled,
and does not really belong in a render method. Maybe add a way to register
special callbacks for a form that allways run before the other callbacks? It
seems forms already add a hidden variable to identify themselves, that could
be used to decide which form-specific callbacks are run.

Currently normal callbacks are not form-specific, are they? I mean, if there
are two forms on a page, and both have a field called 'name', will the two
callbacks for those fields coexist peacefully or will they override each
other?

Also, did you know that many xxx-field classes ignore the :name slot and
just generate a random name (though make-new-callback)? Is this a bug or a
feature?

Well, here's the code, for what it's worth:

(defclass multiple-select-field (select-field)
  ()
  (:default-initargs :name (random-string 8) :client-value ()))

(defmethod render ((field multiple-select-field))
  (<:ai (value field))
  (<:input :type "hidden" :value "x"
           :name (make-new-callback
                  (lambda (value)
                    (declare (ignore value))
                    (do ((vars (slot-value (context.request *context*)
'parameters) (cdr vars))
                         (result ()))
                        ((null vars) (setf (client-value field) result))
                      (if (string= (caar vars) (name field))
                          (push (cdar vars) result))))))
  (<:select :name (name field) :tabindex (tabindex field) :multiple t
            (setf (data-map field) (build-data-map field))
            (render-options field)))

(defmethod render-options ((field multiple-select-field))
  (dolist* ((key-string . value) (data-map field))
    (<:option :value key-string
              :selected  (member key-string (client-value field) :test
#'string=)
              (render-value field value))))

(defmethod value ((field multiple-select-field))
  (mapcar (lambda (x)
            (cdr (assoc x (data-map field) :test #'string=)))
          (client-value field)))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/bese-devel/attachments/20060607/2d080989/attachment.html>


More information about the bese-devel mailing list