LEGAL
#===========================================================================
Copyright (C) 2008 by Nik Ogura. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Bug reports and comments to nik.ogura@gmail.com.
#===========================================================================
NAME
CGI::Lazy::Widget::Dataset
SYNOPSIS
use CGI::Lazy;
our $q = CGI::Lazy->new({
tmplDir => "/templates",
jsDir => "/js",
plugins => {
mod_perl => {
PerlHandler => "ModPerl::Registry",
saveOnCleanup => 1,
},
dbh => {
dbDatasource => "dbi:mysql:somedatabase:localhost",
dbUser => "dbuser",
dbPasswd => "letmein",
dbArgs => {"RaiseError" => 1},
},
session => {
sessionTable => 'SessionData',
sessionCookie => 'frobnostication',
saveOnDestroy => 1,
expires => '+15m',
},
},
});
my $widget = $q->widget->dataset({
id => 'detailBlock',
type => 'multi',
template => "lazydemoDetailBlock.tmpl",
headings => {
template => 'pathwidgetheader.tmpl',
id => 'pathwidgetheader',
},
# nodelete => 1,
lookups => {
prodcodeLookup => {
sql => 'select ID, description from prodCodeLookup',
preload => 1,
orderby => ['ID'],
output => 'hash',
primarykey => 'ID',
},
},
recordset => $q->db->recordset({
table => 'detail',
fieldlist => [
{name => 'detail.ID',
hidden => 1},
{name => 'invoiceid',
hidden => 1},
{name => 'prodCode',
label => 'Product Code',
validator => {rules => ['/\d+/'], msg => 'number only, and is required'}},
{ name => 'quantity',
label => 'Quantity',
validator => {rules => ['/\d+/'], msg => 'number only, and is required'},
outputMask => "%.1f",
},
{name => 'unitPrice',
label => 'Unit Price' ,
validator => {rules => ['/\d+/'], msg => 'number only, and is required'},
inputMask => "%.1f",
},
{name => 'productGross',
label => 'Product Gross' ,
validator => {rules => ['/\d+/'], msg => 'number only, and is required'}},
{name => 'prodCodeLookup.description',
label => 'Product Description',
readOnly => 1 },
],
where => '',
joins => [
{type => 'inner', table => 'prodCodeLookup', field1 => 'prodCode', field2 => 'prodCodeLookup.ID',},
],
orderby => 'detail.ID',
primarykey => 'detail.ID',
}),
});
$q->template->boilerplate($widget)->buildTemplates(); #use a boilerplate object to create template stubs in the buildDir.
DESCRIPTION
CGI::Lazy::Widget::Dataset is, at present, the crown jewel of the CGI::Lazy framework, and the chief reason why the framework was written. Lazy was written because the author has been asked to write front ends to simple databases so often that he started to realize he was writing the same damn code over and over again, and finally got sick of it.
When we're talking about web-based access to a database, there really aren't many operations that we are talking about performing. It all comes down to Select, Insert, Update, and Delete (and Ignore- but more on that later). From the standpoint of the database, it doesn't matter what the data is pertaining to, it could be cardiac patients, or tootsie rolls- the data is still stored in tables, rows and fields, and no matter what you need to read it, modify it, extend it, or destroy it.
The Dataset is designed to, given a set of records, defined by a CGI::Lazy::DB::Recordset object, display that recordset to the screen in whatever manner you like (determined by template and css) and then keep track of the data. It's smart enough to know if a record was retrieved from the db, and therefore should be updated or deleted, or if it came from the web, it must be inserted (or ignored, if it was created clientside, and then subsequently deleted clientside- these records will show on the screen, but will be ignored on submit).
Furthermore, as much of the work as possible is done clientside to cut down on issues caused by network traffic. It's using AJAX and JSON, but there's no eval-ing. All data is passed into the browser as JSON, and washed though a JSON parser.
To do its magic, the Dataset relies heavily on javascript that *should* work for Firefox and IE6. At the time of publication, all functions and methods work flawlessly with FF2, FF3, and IE6. The author has tried to write for W3C standards, and provide as much IE support as his corporate sponsors required. YMMV. Bug reports are always welcome, however we will not support IE to the detrement of W3C standards. Get on board M$.
The API for Lazy, Recordset, and Dataset allows for hooking simple widgets together to generate not-so-simple results, such as pages with Parent/Child 1 to Many relationships between the Datasets. CGI::Lazy::Composite is a wrapper designed to connect Widgets, especially Datasets, together. The Javascript and the Widget templates are highly dependent on each other, and are rather complex. In order to prevent any user (including the author) from having to write them by hand, the CGI::Lazy::Template::Boilerplate object will create a basic, boring, no nonsense template to start from. It won't be the most fancy piece of web automation on the planet, but it will be functional, and can be tweaked to your heart's content.
METHODS
contents (args)
Generates widget contents based on args.
args
Hash of arguments. Common args are mode => 'blank', for displaying a blank data entry form, and nodiv => 1, for sending the contents back without the surrounding div tags (javascript replaces the contents of the div, and we don't want to add another div of the same name inside the div).
display (args)
Displays the widget. Calls $self->contents, and adds preload lookups and instance specific javascript that will not be updated on subsequent ajax calls. Print the return value of this method to STDOUT within a cgi or mod_perl handler.
args
Hash of arguments
displaySingleList (args)
Handler for displaying data when a search returns multiple records. Displays multipleTemplate rather than template.
args
Hash of arguments.
empty ()
Returns the empty property. Property gets set when a search returns nothing.
multi ()
Returns multi property. Multi gets set when a search returns more than one record.
new (q, vars)
Constructor.
q
CGI::Lazy object.
vars
Hashref of object configs.
class => widget class name (lowercase, just as if you were calling $q->widget->$classname) (only necessary if creating widgets automatically, such as members of a Composite widget)
id => widget id (mandatory)
type => widget type (mandatory) 'single' or 'multi'
template => standard template (mandatory)
multipleTemplate => multiple template (mandatory if your searches could ever return multiple results)
headings => 'none' No headings displayed on a multi dataset. If it's anyting other than 'none' its assumed to be the name of a template
headings => 'template name' template to use for headings. Integral div tags assumed.
recordset => CGI::Lazy::RecordSet (mandatory) Can pre-make recordset and pass object reference, or just pass hashref with recordset's particulars, and it'll get created on the fly.
flagColor => color to flag fields that fail validation (defaults to red) (optional)
lookups => (optional)
countryLookup => name of lookup
sql => sql
preload => 1 (0 means no preload, will have to be run via ajax)
orderby => order by clause
output => type of output (see CGI::Lazy::DB)
primarykey => primary key
extravars => Extra variables to be output to template (optional)
name => name of variable
value => variable, string, or reference