August 14, 2006

Dynamic Archetypes forms

This blog entry gives a short introduction about making static Archetypes forms more dynamic

Autogenerated Archetypes forms (generated through the base_edit view) are in general boring static. Often you have the use-case to make forms more dynamic. What means dynamic? Dependent on the value of a particular form element you might be interested e.g. to show or hide other elements of the form. In a recent project we had the case where the user could choose a particular publication mode (daily, weekly, monthly, bi-monthly) for a given document. The widgets for the different publication modes were somewhat complex and bit large since a single widget did consist of serveral other checkboxes. select elements and input fields. It was the customer's wish to present only only one publication widget  that matched the value of the particular publication mode.

So how to approach this problem?

The solution is pretty easy: Javascript + CSS. Using the prototype.js Javascript library (a good documentation can be found here) and the Plone Javascript resource registry it was easy to add an event handler to the select element that controls the publication mode:

  Event.observe(select_id, 'click', observer);

This tells the browser to call the method observer() for every change on the element with the ID select_id. The implementation of the observer() method basically looks like this:

function observer() {
    var v = $F(select_id);

    if (v=='weekly') 
       show_weekly_control()

    if (v=='monthly')
       show_monthly_control()
    ....
}

So everytime you cange the value of the select element the actual value of select element ($F() is a shortcut method (provided by prototype.js)  to obtain the value of a form element independent of its type) is stored in the variable v. For every possible value of v there is a dedicated method that controls the visibility of other form elements:

function show_weekly_control() {
    show_element('archetypes-fieldname-control_weekly');
    hide_element('archetypes-fieldname-control_monthly');
}

function show_monthly_control() {
    hide_element('archetypes-fieldname-control_weekly');
    show_element('archetypes-fieldname-control_monthly');
}

function show_element(id) {
    if ($(id))
        $(id).style.display = 'block';
}

function hide_element(id) {
    if ($(id))
        $(id).style.display = 'none';
}

The archetype-fieldname-XXXXX IDs are autogenerated IDs (by Archetypes) for every field of a schema.

Using this approach we are able to hide and show form elements for general Archetypes forms without hacking any Archetypes or Plone code. I know that this not a complete how-to but it shall point you in the right direction to make more out of your boring Archetype forms.