Why not adopt me?
NAME
HTML::FormFu::Model::DBIC - Integrate HTML::FormFu with DBIx::Class
SYNOPSIS
If using Catalyst, ensure your DBIx::Class schema is placed in the form's stash, by setting this in your application config (MyApp.pm
), where ModelName
is the name of your model that will be passed to $c->model($name)
.
<Controller::HTML::FormFu>
<model_stash>
schema = ModelName
<model_stash>
</Controller::HTML::FormFu>
Set a forms' default values from a DBIx::Class row object:
my $row = $resultset->find( $id );
$form->model->default_values( $row );
Update the database from a submitted form:
if ( $form->submitted_and_valid ) {
my $row = $resultset->find( $form->param('id') );
$form->model->update( $row );
}
METHODS
default_values
Arguments: $dbic_row, [\%config]
Return Value: $form
$form->model->default_values( $row );
Set a form's default values from a DBIx::Class row.
Any form fields with a name matching a column name will have their default value set with the column value.
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 relationships name.
For the following DBIx::Class schemas:
package MySchema::Book;
use strict;
use warnings;
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 strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ Core /);
__PACKAGE__->table("review");
__PACKAGE__->add_columns(
book => { data_type => "INTEGER" },
review => { data_type => "TEXT" },
);
__PACKAGE__->set_primary_key("book");
__PACKAGE__->belongs_to( book => 'MySchema::Book' );
1;
A suitable form for this would be:
elements:
- type: Hidden
name: id
- type: Text
name: title
- type: Block
elements:
- type: Text
name: review
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.
If you want the related row deleted if a particular field is empty, set set $field->model_config->{delete_if_empty}
to true.
elements:
- type: Hidden
name: id
- type: Text
name: title
- type: Block
elements:
- type: Text
name: review
model_config:
delete_if_empty: 1
has_many and many_to_many relationships
To edit fields in related rows with has_many
and many_to_many
relationships, the fields must be placed within a Repeatable element. This will output a repetition of the entire block for each row returned. "increment_field_names" in HTML::FormFu::Element::Repeatable must be true (which is the default value).
The block's nested_name must be set to the name of the relationship.
If you want an extra, empty, copy of the block to be output, to allow the user to add a new row of data, set $block->model_config->{new_empty_row}
. The value must be a column name, or arrayref of column names that must be filled in for the row to be added.
---
element:
- type: Repeatable
nested_name: authors
model_config:
new_empty_row: author
elements:
- type: Hidden
name: id
- type: Text
name: author
If you want to add more than one new row you can use $block->model_config->{new_empty_row_multi}
instead of $block->model_config->{new_empty_row}
. To limit the maximum number of new rows put a range constraint on the count
field.
---
element:
- type: Repeatable
nested_name: authors
model_config:
new_empty_row_multi: author
elements:
- type: Hidden
name: id
- type: Text
name: author
- type: Hidden
name: count
constraints:
- type: Range
max: 3
If you want to provide a Checkbox or similar field, to allow the user to select whether given rows should be deleted (or, in the case of many_to_many
relationships, unrelated), set $block->model_config->{delete_if_true}
to the name of that field. Make sure the name of this field does not clash with one of your DBIx::Class::Row object method names (especially delete).
---
element:
- type: Repeatable
nested_name: authors
model_config:
delete_if_true: deletion_marker
elements:
- type: Hidden
name: id
- type: Text
name: author
- type: Checkbox
name: deletion_marker
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.
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
non-column accessors
To make a form field correspond to a method in your DBIx::Class schema, that isn't a database column or relationship, set $field->model_config->{accessor}
.
---
element:
- type: Text
name: foo
model_config:
accessor: method_name
update
Arguments: [$dbic_row], [\%config]
Return Value: $dbic_row
$form->model->update( $row );
Update the database with the submitted form values. Uses update_or_insert.
See "default_values" for specifics about what relationships are supported and how to structure your forms.
create
Arguments: [\%config]
Return Value: $dbic_row
$form->model->create( $row );
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
To use, ensure the DBIC schema is available on the form stash - see "SYNOPSIS" for an example config - and you must set the appropriate resultset
on the element model_config
:
element:
- type: Select
name: foo
model_config:
resultset: TableClass
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
You can set a condition
, which will be passed as the 1st arguement to "search" in DBIx::Class::ResultSet.
element:
- type: Select
name: foo
model_config:
resultset: TableClass
condition:
type: is_foo
You can set attributes
, which will be passed as the 2nd arguement 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.
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!
SUPPORT
Project Page:
http://code.google.com/p/html-formfu/
Mailing list:
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/html-formfu
Mailing list archives:
http://lists.scsys.co.uk/pipermail/html-formfu/
BUGS
Please submit bugs / feature requests to 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.
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
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.