From 72ee4cbcfbb971c12dc6bd6d540edf96692061ca Mon Sep 17 00:00:00 2001 From: Aaron Trevena Date: Wed, 11 Jan 2006 18:37:36 +0000 Subject: [PATCH] added AsForm git-svn-id: http://svn.maypole.perl.org/Maypole/trunk@449 48953598-375a-da11-a14b-00016c27c3ee --- lib/Maypole/Model/CDBI/AsForm.pm | 800 +++++++++++++++++++++++++++++++ 1 file changed, 800 insertions(+) create mode 100644 lib/Maypole/Model/CDBI/AsForm.pm diff --git a/lib/Maypole/Model/CDBI/AsForm.pm b/lib/Maypole/Model/CDBI/AsForm.pm new file mode 100644 index 0000000..da29578 --- /dev/null +++ b/lib/Maypole/Model/CDBI/AsForm.pm @@ -0,0 +1,800 @@ +package Maypole::Model::CDBI::AsForm; + +use 5.006; + +use strict; +use warnings; + +use base 'Exporter'; +use Data::Dumper; +use Class::DBI::Plugin::Type (); +use HTML::Element; + +our $OLD_STYLE = 0; +# pjs -- Added new methods to @EXPORT +our @EXPORT = qw( to_cgi to_field _to_textarea _to_textfield _to_select + type_of _to_foreign_inputs _to_enum_select _to_bool_select + to_select_from_many _to_select_from_related hasmany_class + _to_hidden _rename_foreign_input _to_readonly + make_param_foreign make_hidden_elmnt make_hidden_elmnt + a_select_box unselect_element do_select search_inputs); + + + +our $VERSION = '2.41'; +# PJS VERSION .05 +# Changes : +# 08-09-05 - fixed broken has_a select box +# - fiked some docs +# - _to_foreign_inputs now takes 3 positional parameters +# (accssr, fields, accssr_meta_info) + + +=head1 NAME + +Maypole::Model:CDBI::AsForm - Produce HTML form elements for database columns + +=head1 SYNOPSIS + + package Music::CD; + use Maypole::Model::CDBI::AsForm; + use base 'Class::DBI'; + use CGI; + ... + + sub create_or_edit { + my $class = shift; + my %cgi_field = $class->to_cgi; + return start_form, + (map { "$_: ". $cgi_field{$_}->as_HTML."
" } + $class->Columns), + end_form; + } + + #
+ # Title:
+ # Artist: + # ... + #
+ +=head1 DESCRIPTION + +This module helps to generate HTML forms for creating new database rows +or editing existing rows. It maps column names in a database table to +HTML form elements which fit the schema. Large text fields are turned +into textareas, and fields with a has-a relationship to other +C tables are turned into select drop-downs populated with +objects from the joined class. + +=head1 METHODS + +The module is a mix-in which adds two additional methods to your +C-derived class. + + +=head2 search_inputs + +Returns hashref of search inputs elements to use in cgi. + +Uses fields specified in search_fields, makes foreign inputs if necessary. + +=cut + +sub search_inputs { + my ($class, $r) = @_; + warn "In model search_inputs " if $class->model_debug; + $class = ref $class || $class; + #my $accssr_class = { $class->accessor_classes }; + my %cgi; + my $sfs = $class->search_fields; + + foreach my $field ( @$sfs ) { + if ( ref $field eq "HASH" ) { # foreign search fields + my ($accssr, $cols) = each %$field; + unless ( @$cols ) { + # default to search fields for related + #$cols = $accssr_class->{$accssr}->search_fields; + die ("$class search_fields error: Must specify at least one column to search in the foreign object named '$accssr'"); + } + my $fcgi = $class->_to_foreign_inputs($accssr, $cols); + # unset the default values for a select box + foreach (keys %$fcgi) { + $class->unselect_element($fcgi->{$_}); + } + $cgi{$accssr} = $fcgi; + #warn "Searchy inputs for field $field is " . Dumper($cgi{$accssr}); + } else { + $cgi{$field} = $class->to_field($field); + $class->unselect_element($cgi{$field}); + } + } + return \%cgi; +} + + +=head2 do_select + +Retrieves object selected from a select box and puts in $r->objects[0]. +The select box input must be named the same as the primary key. + +NOTE only works with tables with single primary key for now. + +=cut + +sub do_select { + my ($self, $r) = @_; + $r->objects([ $self->retrieve($r->params->{$self->primary_column}) ]); + $r->template('view'); +} + + +=head2 unselect_element + +Unselects all options in a HTML::Element of type select. +It does nothing if element is not a select element. + +=cut + +sub unselect_element { + my ($self, $el) = @_; + #unless (ref $el eq 'HTML::Element') { + #$self->_croak ('Need an HTML::Element to unselect. You gave a ' . Dumper($el)); } + if ($el->tag eq 'select') { + foreach my $opt ($el->content_list) { + $opt->attr('selected', undef) if $opt->attr('selected'); + } + } +} + + +# make a select box from args +sub a_select_box { + my ($self, $name, $vals, $selected_val, $contents) = @_; + die "Usage: Need a name and array ref of values to make a select boxes" unless ($name && $vals); + $selected_val ||= ""; + $contents ||= $vals ; + + my $a = HTML::Element->new('select', 'name' => $name); + my $i = 0; + my $c; + foreach my $v ( @$vals ) { + my $opt = HTML::Element->new('option', 'value' => $v); + $opt->attr('selected' => 'selected') if $v eq $selected_val; + $c = $contents->[$i++] || $v; + $opt->push_content($c); + $a->push_content($opt); + } + $a; +} + + +=head2 make_hidden_elmnt + +Makes a hidden HTML::Element and puts it in template_args{hidden_elements} +$model->make_hidden_elmnt($name, $val); + +=cut + +sub make_hidden_elmnt { + my ($self, $r, $col, $val) = @_; + my $elmnt = HTML::Element->new('input', 'type'=>'hidden', 'name'=>$col, 'value'=>$val); + + $r->{template_args}{hidden_elements} ||= []; + push @{ $r->{template_args}{hidden_elements} }, $elmnt; +} + + + +=head2 make_param_foreign + +Makes a new foreign parameter out of parameter and accessor +Just puts accssr__FOREIGN__ in front of param name + +=cut + +sub make_param_foreign { + my ($self, $r, $p, $accssr) = @_; + $r->params->{$accssr . '__FOREIGN__' . $p} = $r->params->{$p}; +} + +=head2 to_cgi + +This returns a hash mapping all the column names of the class to +HTML::Element objects representing form widgets. + +pjs -- added a columns list argument to specify which columns to make +inputs for. + +=cut + +sub to_cgi { + my ($class, @columns) = @_; # pjs -- added columns arg + @columns = $class->columns unless (@columns); + map { $_ => $class->to_field($_) } @columns; +} + + +=head2 to_field($field [, $how]) + +This maps an individual column to a form element. The C argument +can be used to force the field type into one of C, C