mmontone / cl-forms

Web forms handling library for Common lisp
http://mmontone.github.io/cl-forms
MIT License
41 stars 5 forks source link

Form creation from a Mito model? #14

Open vindarel opened 7 months ago

vindarel commented 7 months ago

cl-forms allows to create a form from a model class: https://mmontone.github.io/cl-forms/#Models

where one has to give all the fields, as well as their input type

:fields (forms::make-form-fields
                            `((name :string :label "Name"
                                    :accessor person-name)

I wish we could infer those from a Mito model and create a form with shorter code.

Example:

(defclass book ()

   (title
    :accessor title
    :initarg :title
    :initform nil
    :type string
    :col-type (:varchar 128))

  (title-ascii
    :initform nil 
    ;; etc
   )

   (shelf
    :accessor shelf
    :initform nil
    :col-type (or :null shelf)
    :documentation "Shelf"))

  (:metaclass mito:dao-table-class))

(defclass shelf ()
  ((name
    :initarg :shelf
    :accessor name
    :initform ""
    :col-type (or :null (:varchar 128))))
  (:metaclass mito:dao-table-class))

I found a couple introspection functions:

(mito.class:find-slot-by-name 'book 'shelf)
#<MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS OPENBOOKSTORE.MODELS::SHELF>

(mito.class:table-column-type *)
SHELF  
;; and not (or :null shelf) ?

Ideally we would create a form with all the fields and right types by default and we could exclude some fields (title-ascii).

This would bring us closer to a CRUD admin dashboard… (I got how to list tables and records, adding and editing a record generically is a non-obvious next step).

Any feedback is welcome!

mmontone commented 7 months ago

I suggest you have a look at defform-builder and make-form .

Something like:

(forms:defform-builder mito-form (mito-model)
    (make-instance 'forms::form
                   :name 'mito-form
                   :model mito-model
                   :action "/mito"
                   :method :post
                   :fields (make-fields-from-mito-model (class-of mito-model))

Where make-fields-from-mito-model builds cl-forms:form-field objects from mito types. Wouldn't that work? Let me know if that helps.

mdbergmann commented 7 months ago

Just my 2 cents. While directly coupling the entity model to a HTML form might be quite convenient and nice to have, bit it should be optional, because often times you don't want this coupling and have dedicated UI model.

vindarel commented 7 months ago

thanks I'll have a better look from this.

FWIW, I have a better idea now, here's my notes and a poc that gives me a simple form (but with no relational columns, no form validation, a global message for error reporting). https://github.com/OpenBookStore/openbookstore/blob/master/src/web/mito-admin/mito-forms.lisp

@mdbergmann yeah in my scenario defining such a form is optional and comes after and independently of the DB model. I wouldn't rely exclusively on such a CRUD dashboard either, I would create the most important forms from scratch, but having automatic forms is nice to have with DB models that are less important but that the user needs to edit from time to time.

mmontone commented 7 months ago

Just my 2 cents. While directly coupling the entity model to a HTML form might be quite convenient and nice to have, bit it should be optional, because often times you don't want this coupling and have dedicated UI model.

My suggestion is to use a generic-function for view creation. Default implementation returns the reified form from the mito model. Specialize the generic function on the type of object for a custom view. That's what I use in https://codeberg.org/mmontone/mold-desktop .