views_ui reloaded

Stepping up to the plate

Back to our story of Ajax vs the Drupal Form API. After modifying poll.module to work with ahah_forms in a couple of hours, I was feeling cocky, and decided to go for the gold ring: Views. I use views a lot and think it is one of the key drupal modules.  And it is the perfect target for Ajax, because creating a View can take over a dozen page refreshes.  I went in optimistic.  If you read my first post on this topic ( )
you will remember that the hardest part of the process is getting your dynamic form to work without JavaScript, and views_ui already had that nailed.  At the end of my first day's work I thought I was 90% of the way there.  At the end of my second day, I knew I was in trouble.

Update: I have just released version 1.3 of ahah_forms, which includes a significantly simplified version of views_ui.module-example.  I realized that since I was not able to accomplish my goal of per-section form processing, I can limit most of my changes to the theming functions. Most of the discussion below is still valid.

The Four Steps

I had abstracted four steps to working with a dynamic subform:

  1. Pull existing info about the subform from the $node (which comes from the db), or from the $_POST, into an intermediate data structure.
  2. Process any commands (add/edit/delete) in the $_POST, updating the data structure
  3. Convert the data structure into a form array
  4. Add the subform controls to the form array

It turns out there are quite a few unspoken assumptions here that make this work smoothly for Ajax.  Views_ui did all those step, more or less, but not in a way I could easily work with.  So here are some rules of thumb for easier Ajaxing:

  • Do all of these steps for each subform before moving on to the next.  Views_ui tends to do a single step for all the subforms before moving on to the next step
  • Do all of these steps in the form creation step of the formAPI. Views_ui does some of the steps in the theme stage.
  • Have descrete theming functions for each subform, and use #theme to apply them.
  • It's easier to cheat and access parameters in $_POST, than to do things the correct formAPI dynamic form way, which is to rebuild the form, apply the $_POST  to the form with drupal_process_form (happen automatically if you use drupal_get_form), and then access the form values.  Ugh.  This one will probably come back to bite me, and hopefully is just be my current stage of formAPI ignorence, but it feels brittle when it comes to fragments.
  • Avoid logic in your theme stage as much as possible.

Once I figured out all of those issues, I just needed to:

  1. Add #ahah_binding to the subforms and interesting buttons
  2. Sprinkle in wrappers for all the subforms (note: fieldsets make crappy wrappers, b/c you can't regenerate the legends).
  3. Make sure all of the interface elements had appropriate classes or ids.
  4. Add a menu item and function for updating and building a subform
  5. Change some #value elements to #hiddens, so the Javascript could see them.
  6. And rewrite my ahah_forms.js to return more info about the element clicked (again to accomidate formAPI processing, more about this in my next post).
  7. Throw in a little custom Javascript to deal with the Expose filter button, with is the only element that updates a wrapper it is not part of (I love jQuery: $('#exposed_filter_fieldset.collapsed legend a).click() is just a joy to behold).

The Nitty Gritty

For those of you who want more details, here is an overview of the changes I made along with the names of the involved functions (function_x means I added a set of functions, one for each subform. ei: views_ui_edit_form_field, views_ui_edit_form_argument, etc)

  1. Broke views_edit_view (main form builder function), up into
    multiple smaller per-section form builder functions. Small form builder
    functions set #theme for each section form [views_edit_view, views_ui_edit_form_x & views_ui_edit_form_section]
  2. Removed _views_check_ops, and spread it's functionality into the per-section form builders [_views_check_ops]
  3. Broke theme_views_edit_view up likewise.  Pulled sections in with druapl_render($form[ section ]); [theme_views_ui_edit_x_section, theme_views_edit_view, views_ui_render_section]
  4. Added wrappers in theme_views_edit_view (had to add div, fieldsets don't make good wrapper, since legend gets erased) [theme_views_edit_view] .
  5. Added #ahah_bindings to add button and views_image_buttons to each section, and to expose filter in filter section [views_ui_edit_form_section, views_ui_add_add_button, views_ui_edit_form_filters]
  6. Added class attributes and section name to the generated buttons, so I can do step 4 [views_ui_add_button, views_ui_add_buttons, theme_views_imagebutton, views_ui_add_filter].
  7. Added views_ui_admin_build_view_js to be called from the javascript, and a menu item for it [views_ui_admin_build_view_js]

Again, if you'd like to try it out for yourself, go to and create some views.  Let me know what you think.

not sure if the demo site is

not sure if the demo site is allowing logins...

It's being fussy

It does seem awfully fussy doesn't it? I don't know if it is an issue of having lots of people login with the same username/pass , or if it is a some particular Drupal 5.1 vs PHP 4.4.4 interaction. Anyway, I will just allow anonymous people to admin views for a while.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.