HTML::FormFu::Model::DUser3Contributed Perl DocumeHTML::FormFu::Model::DBIC(3)NAMEHTML::FormFu::Model::DBIC - Integrate HTML::FormFu with DBIx::Class
SYNOPSIS
Example of typical use in a Catalyst controller:
sub edit : Chained {
my ( $self, $c ) = @_;
my $form = $c->stash->{form};
my $book = $c->stash->{book};
if ( $form->submitted_and_valid ) {
# update dbic row with submitted values from form
$form->model->update( $book );
$c->response->redirect( $c->uri_for('view', $book->id) );
return;
}
elsif ( !$form->submitted ) {
# use dbic row to set form's default values
$form->model->default_values( $book );
}
return;
}
SETUP
For the form object to be able to access your DBIx::Class schema, it
needs to be placed on the form stash, with the name "schema".
This is easy if you're using Catalyst-Controller-HTML-FormFu, as you
can set this up to happen in your Catalyst app's config file.
For example, if your model is named "MyApp::Model::Corp", you would set
this (in Config::General format):
<Controller::HTML::FormFu>
<model_stash>
schema Corp
</model_stash>
</Controller::HTML::FormFu>
Or if your app's config file is in YAML format:
'Controller::HTML::FormFu':
model_stash:
schema: Corp
METHODS
default_values
Arguments: $dbic_row, [\%config]
Return Value: $form
$form->model->default_values( $dbic_row );
Set a form's default values from the database, to allow a user to edit
them.
update
Arguments: [$dbic_row], [\%config]
Return Value: $dbic_row
$form->model->update( $dbic_row );
Update the database with the submitted form values.
create
Arguments: [\%config]
Return Value: $dbic_row
my $dbic_row = $form->model->create( {resultset => 'Book'} );
Like "update", but doesn't require a $dbic_row argument.
You need to ensure the DBIC schema is available on the form stash - see
"SYNOPSIS" for an example config.
The "resultset" must be set either in the method arguments, or the form
or block's "model_config".
An example of setting the ResultSet name on a Form:
---
model_config:
resultset: FooTable
elements:
# [snip]
options_from_model
Populates a multi-valued field with values from the database.
This method should not be called directly, but is called for you during
"$form->process" by fields that inherit from
HTML::FormFu::Element::_Group. This includes:
HTML::FormFu::Element::Select
HTML::FormFu::Element::Checkboxgroup
HTML::FormFu::Element::Radiogroup
HTML::FormFu::Element::ComboBox
To use you must set the appropriate "resultset" on the element
"model_config":
element:
- type: Select
name: foo
model_config:
resultset: TableClass
BUILDING FORMS
single table
To edit the values in a row with no related rows, the field names
simply have to correspond to the database column names.
For the following DBIx::Class schema:
package MySchema::Book;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("book");
__PACKAGE__->add_columns(
id => { data_type => "INTEGER" },
title => { data_type => "TEXT" },
author => { data_type => "TEXT" },
blurb => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("id");
1;
A suitable form for this might be:
elements:
- type: Text
name: title
- type: Text
name: author
- type: Textarea
name: blurb
might_have and has_one relationships
Set field values from a related row with a "might_have" or "has_one"
relationship by placing the fields within a Block (or any element that
inherits from Block, such as Fieldset) with its "nested_name" in
HTML::FormFu set to the relationship name.
For the following DBIx::Class schemas:
package MySchema::Book;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("book");
__PACKAGE__->add_columns(
id => { data_type => "INTEGER" },
title => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->might_have( review => 'MySchema::Review', 'book' );
1;
package MySchema::Review;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("review");
__PACKAGE__->add_columns(
id => { data_type => "INTEGER" },
book => { data_type => "INTEGER", is_nullable => 1 },
review_text => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("book");
__PACKAGE__->belongs_to( book => 'MySchema::Book' );
1;
A suitable form for this would be:
elements:
- type: Text
name: title
- type: Block
nested_name: review
elements:
- type: Textarea
name: review_text
For "might_have" and "has_one" relationships, you generally shouldn't
need to have a field for the related table's primary key, as
DBIx::Class will handle retrieving the correct row automatically.
You can also set a "has_one" or "might_have" relationship using a multi
value field like Select.
elements:
- type: Text
name: title
- type: Select
nested: review
model_config:
resultset: Review
This will load all reviews into the select field. If you select a
review from that list, a current relationship to a review is removed
and the new one is added. This requires that the primary key of the
"Review" table and the foreign key do not match.
has_many and many_to_many relationships
The general principle is the same as for "might_have" and "has_one"
above, except you should use a Repeatable element instead of a Block,
and it needs to contain a Hidden field corresponding to the foreign
key.
The Repeatable block's nested_name must be set to the name of the
relationship.
The Repeable block's increment_field_names must be true (which is the
default value).
The Repeable block's counter_name must be set to the name of a Hidden
field, which is placed outside of the Repeatable block. This field is
used to store a count of the number of repetitions of the Repeatable
block were created. When the form is submitted, this value is used
during "$form->process" to ensure the form is rebuilt with the correct
number of repetitions.
For the following DBIx::Class schemas:
package MySchema::Book;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("book");
__PACKAGE__->add_columns(
id => { data_type => "INTEGER" },
title => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many( review => 'MySchema::Review', 'book' );
1;
package MySchema::Review;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("review");
__PACKAGE__->add_columns(
book => { data_type => "INTEGER" },
review_text => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("book");
__PACKAGE__->belongs_to( book => 'MySchema::Book' );
1;
A suitable form for this would be:
elements:
- type: Text
name: title
- type: Hidden
name: review_count
- type: Repeatable
nested_name: review
counter_name: review_count
elements:
- type: Hidden
name: book
- type: Textarea
name: review_text
many_to_many selection
To select / deselect rows from a "many_to_many" relationship, you must
use a multi-valued element, such as a Checkboxgroup or a Select with
multiple set.
The field's name must be set to the name of the "many_to_many"
relationship.
default_column
If you want to search / associate the related table by a column other
it's primary key, set "$field->model_config->{default_column}".
---
element:
- type: Checkboxgroup
name: authors
model_config:
default_column: foo
link_values
If you want to set columns on the link table you can do so if you add a
"link_values" attribute to "model_config":
---
element:
- type: Checkboxgroup
name: authors
model_config:
link_values:
foo: bar
additive
The default implementation will first remove all related objects and
set the new ones (see
<http://search.cpan.org/perldoc?DBIx::Class::Relationship::Base#set_$rel>).
If you want to add the selected objects to the current set of objects
set "additive" in the "model_config".
---
element:
- type: Checkboxgroup
name: authors
model_config:
additive: 1
options_from_model: 0
"options_from_model" is set to 0 because it will try to fetch all
objects from the result class "Authors" if "model_config" is specified
without a "resultset" attribute.)
COMMON ARGUMENTS
The following items are supported in the optional "config" hash-ref
argument to the methods default_values, update and create.
base
If you want the method to process a particular Block element,
rather than the whole form, you can pass the element as a "base"
argument.
$form->default_values(
$row,
{
base => $formfu_element,
},
);
nested_base
If you want the method to process a particular Block element by
name, you can pass the name as an argument.
$form->default_values(
$row,
{
nested_base => 'foo',
}'
);
CONFIGURATION
Config options for fields
The following items are supported as "model_config" options on form
fields.
accessor
If set, "accessor" will be used as a method-name accessor on the
"DBIx::Class" row object, instead of using the field name.
delete_if_empty
Useful for editing a "might_have" related row containing only one
field.
If the submitted value is blank, the related row is deleted.
For the following DBIx::Class schemas:
package MySchema::Book;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("book");
__PACKAGE__->add_columns(
id => { data_type => "INTEGER" },
title => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->might_have( review => 'MySchema::Review', 'book' );
1;
package MySchema::Review;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("review");
__PACKAGE__->add_columns(
book => { data_type => "INTEGER" },
review_text => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("book");
__PACKAGE__->belongs_to( book => 'MySchema::Book' );
1;
A suitable form for this would be:
elements:
- type: Text
name: title
- type: Block
nested_name: review
elements:
- type: Text
name: review_text
model_config:
delete_if_empty: 1
label
To use a column value for a form field's label.
Config options for fields within a Repeatable block
delete_if_true
Intended for use on a Checkbox field.
If the checkbox is checked, the following occurs: for a has-many
relationship, the related row is deleted; for a many-to-many
relationship, the relationship link is removed.
An example of use might be:
elements:
- type: Text
name: title
- type: Hidden
name: review_count
- type: Repeatable
nested_name: review
counter_name: review_count
elements:
- type: Hidden
name: book
- type: Textarea
name: review_text
- type: Checkbox
name: delete_review
label: 'Delete Review?'
model_config:
delete_if_true: 1
Note: make sure the name of this field does not clash with one of
your DBIx::Class::Row method names (e.g. "delete") - see "CAVEATS".
Config options for Repeatable blocks
empty_rows
For a Repeatable block corresponding to a has-many or many-to-many
relationship, to allow the user to insert new rows, set
"empty_rows" to the number of extra repetitions you wish added to
the end of the Repeatable block.
new_rows_max
Set to the maximum number of new rows that a Repeatable block is
allowed to add.
If not set, it will fallback to the value of "empty_rows".
Config options for options_from_model
The column used for the element values is set with the "model_config"
value "id_column" - or if not set, the table's primary column is used.
element:
- type: Select
name: foo
model_config:
resultset: TableClass
id_column: pk_col
The column used for the element labels is set with the "model_config"
value "label_column" - or if not set, the first text/varchar column
found in the table is used - or if one is not found, the "id_column" is
used instead.
element:
- type: Select
name: foo
model_config:
resultset: TableClass
label_column: label_col
To pass the database label values via the form's localization object,
set "localize_label"
element:
- type: Select
name: foo
model_config:
localize_label: 1
You can set a "condition", which will be passed as the 1st argument to
"search" in DBIx::Class::ResultSet.
element:
- type: Select
name: foo
model_config:
resultset: TableClass
condition:
type: is_foo
You can set a "condition_from_stash", which will be passed as the 1st
argument to "search" in DBIx::Class::ResultSet.
"key" is the column-name to be passed to search, and "stash_key" is the
name of a key on the form stash from which the value to be passed to
search is found.
element:
- type: Select
name: foo
model_config:
resultset: TableClass
condition_from_stash:
key: stash_key
Is comparable to:
$form->element({
type => 'Select',
name => 'foo',
model_config => {
resultset => 'TableClass',
condition => {
key => $form->stash->{stash_key}
}
}
})
You can set "attributes", which will be passed as the 2nd argument to
"search" in DBIx::Class::ResultSet.
FAQ
Add extra values not in the form
To update values to the database which weren't submitted to the form,
you can first add them to the form with add_valid.
my $passwd = generate_passwd();
$form->add_valid( passwd => $passwd );
$form->model->update( $row );
"add_valid" works for fieldnames that don't exist in the form.
Set a field read only
You can make a field read only. The value of such fields cannot be
changed by the user even if they submit a value for it.
$field->model_config->{read_only} = 1;
- Name: field
model_config:
read_only: 1
See HTML::FormFu::Element::Label.
CAVEATS
To ensure your column's inflators and deflators are called, we have to
get / set values using their named methods, and not with "get_column" /
"set_column".
Because of this, beware of having column names which clash with
DBIx::Class built-in method-names, such as "delete". - It will have
obviously undesirable results!
REMOVED METHODS
new_empty_row
See "empty_rows" in "Config options for Repeatable blocks" instead.
new_empty_row_multi
See "new_rows_max" in "Config options for Repeatable blocks" instead.
Range constraint
See "empty_rows" in "Config options for Repeatable blocks" instead.
SUPPORT
Project Page:
http://code.google.com/p/html-formfu/ <http://code.google.com/p/html-
formfu/>
Mailing list:
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/html-formfu
<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/html-formfu>
Mailing list archives:
http://lists.scsys.co.uk/pipermail/html-formfu/
<http://lists.scsys.co.uk/pipermail/html-formfu/>
BUGS
Please submit bugs / feature requests to
http://code.google.com/p/html-formfu/issues/list
<http://code.google.com/p/html-formfu/issues/list> (preferred) or
<http://rt.perl.org>.
SUBVERSION REPOSITORY
The publicly viewable subversion code repository is at
http://html-formfu.googlecode.com/svn/trunk/HTML-FormFu-Model-DBIC
<http://html-formfu.googlecode.com/svn/trunk/HTML-FormFu-Model-DBIC>.
If you wish to contribute, you'll need a GMAIL email address. Then just
ask on the mailing list for commit access.
If you wish to contribute but for some reason really don't want to sign
up for a GMAIL account, please post patches to the mailing list
(although you'll have to wait for someone to commit them).
If you have commit permissions, use the HTTPS repository url:
https://html-formfu.googlecode.com/svn/trunk/HTML-FormFu-Model-DBIC
<https://html-formfu.googlecode.com/svn/trunk/HTML-FormFu-Model-DBIC>
SEE ALSO
HTML::FormFu, DBIx::Class, Catalyst::Controller::HTML::FormFu
AUTHOR
Carl Franks
CONTRIBUTORS
Based on the code of "DBIx::Class::HTML::FormFu", which was contributed
to by:
Adam Herzog
Daisuke Maki
Mario Minati
COPYRIGHT AND LICENSE
Copyright (C) 2007 by Carl Franks
Based on the original source code of DBIx::Class::HTMLWidget, copyright
Thomas Klausner.
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, either Perl version 5.8.8 or, at
your option, any later version of Perl 5 you may have available.
perl v5.14.1 2011-03-17 HTML::FormFu::Model::DBIC(3)