Home | Wiki | OI 1.x Docs | OI 2.x Docs |
As of version 1.30, OpenInteract supports the idea of template widgets. A widget is a common element into which you can just plug in text or parameters to customize it. For example, an 'INPUT' element of type 'TEXT' is a particular type of widget -- you can customize its size, name, and default value.
Widgets can also include other widgets. Such as a row that uses the 'INPUT TEXT' widget described above to create a labeled input field, with a label on the left and the input widget on the right.
One of the main benefits of using these over HTML is that these are centralized -- a change in one place enacts changes throughout your site. All column headers can look a certain way and be changed easily, all textboxes can be consistent and you can create widgets specific to your site and needs -- such as for inputting dates or money, or displaying addresses-- for a consistent user interface.
Here's an example:
[%######################################## form_text( name, value, size, maxlength, field_label ) Generate a simple text field. Defaults: size = 20 maxlength = 50 ########################################-%] [%- DEFAULT size = 20; DEFAULT maxlength = 50; -%] [%- field_pre_label -%] <input type="text" name="[% name %]" value="[% value %]" size="[% size %]" maxlength="[% maxlength %]"> [%- field_label -%] |
And you would reference this like:
[% INCLUDE form_text( name = "batting_average", value = ".389" size = 5 ) -%] |
And when the template is processed, get in return:
<input type="text" name="batting_average" value=".389" size="5" maxlength="50"> |
Calling widgets from other widgets is just as simple:
[%######################################## label_form_text_row( label, count, name, value, field_label ) Display a row to input text: label on left, text input on right. Defaults: colspan = 2 ########################################-%] [%- DEFAULT colspan = 2; -%] [%- INCLUDE label_row_begin( colspan = 1 ) -%] [%- INCLUDE data_cell_begin %][% INCLUDE form_text %] </td></tr> |
Here we call three separate items, two of which ('label_row_begin' and 'data_cell_begin') aren't really 'widgets' but rather just named areas for common code. This might be called:
[% INCLUDE label_form_text_row( label = 'Batting Average', name = 'batting_average', value = '.389', size = 5 ) -%] |
And result in:
<tr valign="middle"> <td align="right"><b>Batting Average</b></td> <td align="right"> <input type="text" name="batting_average" value=".389" size="5" maxlength="50"> </td> </tr> |
And you're not restricted to simple fill-in elements either. You can represent a common data-oriented widget -- such as a drop-down box representing countries your company services -- in this manner as well. Here's how such a call might look:
[%# Use USA as default, antagonizing the rest of the world...-%] [%- picked_country = user.country || 'United States' -%] [% INCLUDE label_form_country_select( label = 'Countries', name = 'country', picked = picked_country ) -%] |
Using this, the page designer doesn't care how many countries the company services, whether a new one has been added to the list, etc. Just make the call and the graphic element will be created the same way every time.
Using these template widgets you can build a library of display elements very quickly.
As of version 1.30, OpenInteract comes with the following widgets:
Every website has its own copy of the widgets in the website template/ directory, so if you want to modify the appearance of any of these items, you can. For instance, if you want to pass in a Spanish equivalent for labels, you can modify 'show_label', which is currently the ultra-simple:
[%######################################## show_label( label ) Display a label. ########################################-%] <b>[% label %]</b> |
with:
[%######################################## show_label( label, spanish ) Display a label (displaying spanish version if available) ########################################-%] <b>[% label %]</b> [% IF spanish %](<em>[% spanish %]<em>)[% END -%] |
When you create a website you have a number of widgets
installed by default in the $WEBSITE_DIR/template
directory. These widgets will never be overwritten unless you
ask them to be (via the oi_manage refresh_widget
command) and they are specific to your website. You can add new
ones, remove existing ones -- whatever you like
If you have an existing website and want the widgets with OI 1.30+, just run:
$ export OIWEBSITE=/path/to/my/website $ oi_manage refresh_widget
The Template Toolkit docs warn about this, but it's worth reiterating. You can use either the INCLUDE or PROCESS directives to run these widgets. The difference between them is subtle.
For instance, say you have the following:
[% PROCESS form_text( name = 'this', value = 'that' ) %] [% PROCESS form_select( name = 'them', list = object_list, value_field = 'id', label_field = 'full_name' ) %]
You'd be extremely surprised to find your SELECT box being 20 rows long! that's because inside the 'form_text' widget there's a statement:
[% DEFAULT size = 20 %]
Since we didn't pass any value for 'size' into 'form_text', it's set to 20. But the tricky part is that this value is also passed into the 'form_select' widget since it's in our environment and we didn't pass it explicitly in the PROCESS call.
You could argue that instead of using DEFAULT we should do something like:
[% text_size = size || 20 %]
So that the common variable 'size' isn't set as a side-effect. And that's a valid argument. But then as a widget writer you have to have knowledge of the variables the other widgets are using. And as a widget user you have to have knowledge of what happens inside the widget.
With these potential pitfalls, why use PROCESS at all? The Template Toolkit manual states that using PROCESS is a little faster. So you have a trade-off to make: a little speed for knowledge that things will work like you think they will.
The template widgets shipped with OpenInteract fall on the side of being able to sleep at night -- every widget works like you think it should. (Or at least how someone thought it should.) You can always change them for you site if you like, but we've found it's better to use INCLUDE and not deal with the potential headaches. If you're sure the widget won't have any side effects -- that it doesn't have any DEFAULT or other variable modification statements -- then go ahead and use PROCESS.