Forum OpenACS Development: Forms/Metadata Part Two

Posted by Barry Books on
Extend datamodel to support forms

Below is a table with the arguments for form elements and possible data to populate them.

Element            Current Data            Proposed Data
widget                                     datatypes.widget       
datatype           acs_attributes.datatype
html                                       attributes.html     
options                                    ???
value              acs_attribute.default_value
values                                     acs_attribute.default_values (multi value)
validate                                   datatypes.validate (multi value)
optional           acs_attributes.min_n_values/max_n_values 
Should validate/widget be part of the datatype or attribute?

I'm for making datatypes acs_objects. This does a couple of things. First it allows access control which might be needed for some kinds of RAD tools. It also adds a parent/child relation to the datatypes. This is usefull in a number of ways. Create a few types such as number, string and long_string. If I want to collect animals I can create a datatype called animals with a parent of string. I don't really need a new widget or validate routines. If I like dogs I create a new type dogs and make its parent animals. I still don't need new validate routines. Now if I only want pure breed dogs I can create datatype called purebreed with a parent of dogs. Next I create a table of valid types and validate against that. The widget can also change to a select list. If the user has write access to the datatype they could add a new breed. Finally this allows finding all the animals or dogs in the system.

Multiple values per attributes

The current datamodel is incomplete when it comes to multi value storage for one attribute, but html forms allow this. The min_n_values/max_n_values imply you can store more than one value per attribute but the data model but it's not clear what happens if you set max greater than 1. I think the way to do this is add a new storage type called generic_multi and create a table like:

key is a primary key
field_id/object_id are unique
v_object_id must be an object_id
This would require a new set of acs_object apis like get_multiattribute, set_multiattribute and delete_multiattribute. This allows some kind of typed storage as well as objects to be stored inside objects.
Posted by Jeff Davis on
What would you do for a datatype where two fields were interdependent (say an address where if country was US you used a select widget for the State but if CA you used a select widget for Province). Also, in that case how would you handle multifield validations?
Posted by Barry Books on
Addresses are a big problem. If you pick the country first then go to a page to fill in an address it's easy enough, just make a US address datatype and a Canada address datatype. If you what to switch interfaces without a trip the the server then things are much more complicated. I guess you could include both and javascript the visiblity.

Multifield validation is a problem also. On my current project I do single field automatically and multifield with custom code. This works pretty well but I don't do much multifield validation.

Posted by Jeff Davis on
Barry, the having a canada address datatype and us address datatype is at odds with how address datamodels are written. generally you conflate state/province into one field and either have a different form for the two or you validate state/province based on country.

My point is more that it's not necessarily a good idea to presume a single widget for a given field will be adequate. Certainly for a basic "one size fits all" rapid prototype the generic interface it will be ok but cms has something almost exactly like this already (with the added bonus of the ability to populate widget params from the db or evaled tcl code) and it is not up to the job for real forms either.

Also, on one to many I suspect it would be better to just create tables for the 1-N types rather than a table with a union of all possible data types in it. there is a table field in the acs_attributes table already for that purpose.

Posted by Barry Books on
I think we mostly agree but I think I see your problem. BTW I like CMS, it just does not seem useful for auto generating a bunch of admin forms.

Addresses are a good example because I think it's possible to have one datamodel to store most addresses, but you need multiple user interfaces depending on local or user preferences. In my case I need to collect US and Canada addresses. Some people need to enter either. Some people only want to enter US and don't want a country box. Some want ZIP+4 others want full state names and still others want the two character states.

If you build a address object with a generic data model then build a US address object with a supertype of address then you should be able to override the state attribute with an enum list of the 50 US states but still store the data in the generic tables.

How the whole UI works is a different problem because you would want an address widget to display/collect the data. It might be possible in some cases to rework the UI based on the datatype but in the general case I think you would need custom widgets for most datatypes.

I don't really see this as way to auto generate all forms and save code. I actually like the ad_page_contract model with pluggable filers and call address_widget to get the html form, but users like the ever forward, error by the input box model of the form templates. This has been a constant battle for me so I started moving to form templates but it seems like the pieces don't quite fit together. Just looking thru the code it seems only a few packages use the form templates, what feedback to other people have about the press back to fix your errors interface? Of couse I just hit back to fix some mistakes and my browser presented me with a black form.

Posted by Don Baccus on
We're very much pushing folks to use ad_form (which calls the form-builder) to implement self-submit forms in order to get the in-form error messages.  ad_form's still not generalized to the point where it covers all cases that people want to implement but it's getting closer.

That will be our preferred way to build forms "by hand."  To get a very simplistic overview in a real package checkout the "populate" package in the contrib part of the OpenACS 4.6.1 tarball.

And of course the track being discussed here is to move forward another step, automatic form generation and handling where possible.  I'm not going to butt into that discussion at the moment (haven't played enough with the existing CMS form stuff to feel comfortable talking about its pluses/minuses), just wanted to emphasize that ad_form, with its ad_page_contract declarative flavor, is what we want people to use if possible rather than call the form builder "by hand".  It's easier and more readable when the form handling you're implementing fits what it can do and it's being extended on a regular basis to cover cases it can't currently.

Posted by Barry Books on
I finally tracked down ad_form. It appears to solve the problem of how to get objects into the database from forms and seems possible to layer on it building the form. I'm going to download it and see if it will work in my version.