Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add 'use_init_obj_when_no_accessor_in_item' flag for dual-purpose ini…

…t_obj
  • Loading branch information...
commit 5032221f2ed0603965285ca17be5f2a3cda359f5 1 parent 46cd0b8
@gshank authored
View
11 lib/HTML/FormHandler.pm
@@ -660,8 +660,14 @@ not map to an existing or database object in an automatic way, and you need
to create a different type of object for initialization. (You might also
want to do 'update_model' yourself.)
-Also see the 'use_init_obj_over_item' flag, if you want to provide both an
-item and an init_object, and use the values from the init_object.
+Also see the 'use_init_obj_over_item' and the 'use_init_obj_when_no_accessor_in_item'
+flags, if you want to provide both an item and an init_object, and use the
+values from the init_object.
+
+The 'use_init_obj_when_no_accessor_in_item' flag is particularly useful
+when some of the fields in your form come from the database and some
+are process or environment type flags that are not in the database. You
+can provide defaults from both a database row and an 'init_object.
=head3 ctx
@@ -912,6 +918,7 @@ has 'defaults' => ( is => 'rw', isa => 'HashRef', default => sub {{}}, traits =>
);
has 'use_defaults_over_obj' => ( is => 'rw', isa => 'Bool', clearer => 'clear_use_defaults_over_obj' );
has 'use_init_obj_over_item' => ( is => 'rw', isa => 'Bool', clearer => 'clear_use_init_obj_over_item' );
+has 'use_init_obj_when_no_accessor_in_item' => ( is => 'rw', isa => 'Bool' );
has 'use_fields_for_input_without_param' => ( is => 'rw', isa => 'Bool' );
# flags
has [ 'verbose', 'processed', 'did_init_obj' ] => ( isa => 'Bool', is => 'rw' );
View
5 lib/HTML/FormHandler/Field.pm
@@ -360,8 +360,9 @@ the other. Now 'default' does *not* override.
If you pass in a model object with C<< item => $row >> or an initial object
with C<< init_object => {....} >> the values in that object will be used instead
of values provided in the field definition with 'default' or 'default_fieldname'.
-If you want defaults that override the item/init_object, you can use the form
-flags 'use_defaults_over_obj' and 'use_init_obj_over_item'.
+If you want defaults that override or supplement the item/init_object, you can use the form
+flags 'use_defaults_over_obj', 'use_init_obj_over_item', and
+'use_init_obj_when_no_accessor_in_item'.
You could also put your defaults into your row or init_object instead.
View
17 lib/HTML/FormHandler/InitResult.pm
@@ -79,6 +79,7 @@ sub _result_from_object {
return unless ( $item || $self->has_fields ); # empty fields for compounds
my $my_value;
+ my $init_obj = $self->form->init_object;
for my $field ( $self->sorted_fields ) {
next if ( $field->inactive && !$field->_active );
my $result = HTML::FormHandler::Field::Result->new(
@@ -87,7 +88,18 @@ sub _result_from_object {
);
if ( (ref $item eq 'HASH' && !exists $item->{ $field->accessor } ) ||
( blessed($item) && !$item->can($field->accessor) ) ) {
- $result = $field->_result_from_fields($result);
+ my $found = 0;
+ if ($field->form->use_init_obj_when_no_accessor_in_item) {
+ # if we're using an item, look for accessor not found in item
+ # in the init_object
+ my @names = split( /\./, $field->full_name );
+ my $init_obj_value = $self->find_sub_item( $init_obj, \@names );
+ if ( defined $init_obj_value ) {
+ $found = 1;
+ $result = $field->_result_from_object( $result, $init_obj_value );
+ }
+ }
+ $result = $field->_result_from_fields($result) unless $found;
}
else {
my $value = $self->_get_value( $field, $item ) unless $field->writeonly;
@@ -102,6 +114,9 @@ sub _result_from_object {
return $self_result;
}
+# this is used for reloading repeatables form the database if they've changed and
+# for finding field values in the init_object when we have an item and the
+# 'use_init_obj_when_no_accessor_in_item' flag is set
sub find_sub_item {
my ( $self, $item, $field_name_array ) = @_;
my $this_fname = shift @$field_name_array;;
View
11 lib/HTML/FormHandler/Manual/Defaults.pod
@@ -63,6 +63,17 @@ and set the 'use_init_obj_over_item' flag:
Note that the 'use_init_obj_over_item' and 'use_defaults_over_obj' flags
are automatically cleared (if you're using persistent forms).
+For forms where some defaults come from a database row, and some defaults
+come from some other dynamic source (so that putting them into the field
+definitions doesn't make sense), you can use the
+'use_init_obj_when_no_accessor_in_item' flag to provide two different
+sets of defaults, one set in the 'item' (usually a db row) and one set in
+the init_obj. If the 'item' is undefined, the values in the init_object
+are used.
+
+ in form: has '+use_init_obj_when_no_accessor_in_item' => ( default => 1 );
+ $form->process( item => $item, init_object => { foo => '...' }, .. );
+
There is a convenience method for setting 'defaults' on a number of fields at
once, the form's 'defaults' attribute, which uses the same mechanism as
'update_field_list' but only sets defaults. Note that this hashref is
View
52 t/form_setup/init_obj.t
@@ -0,0 +1,52 @@
+use strict;
+use warnings;
+use Test::More;
+
+{
+ package Test::Form;
+ use HTML::FormHandler::Moose;
+ extends 'HTML::FormHandler';
+
+ has '+use_init_obj_when_no_accessor_in_item' => ( default => 1 );
+ has_field 'foo';
+ has_field 'bar';
+ has_field 'max';
+ has_field 'my_comp' => ( type => 'Compound' );
+ has_field 'my_comp.one';
+ has_field 'my_comp.two';
+}
+
+my $form = Test::Form->new;
+my $item = { foo => 'item_foo', bar => 'item_bar' };
+my $init_obj = { max => 'init_obj_max' };
+
+$form->process( item => $item, init_object => $init_obj, params => {} );
+is( $form->field('foo')->fif, 'item_foo' );
+is( $form->field('bar')->fif, 'item_bar' );
+is( $form->field('max')->fif, 'init_obj_max', 'init_obj value pulled in' );
+
+$init_obj = { my_comp => { one => 'init_obj_one', two => 'init_obj_two' } };
+$form->process( item => $item, init_object => $init_obj, params => {} );
+is( $form->field('foo')->fif, 'item_foo' );
+is( $form->field('bar')->fif, 'item_bar' );
+is( $form->field('max')->fif, '' );
+is( $form->field('my_comp.one')->fif, 'init_obj_one', 'init_obj value pulled in for compound' );
+
+$init_obj = { foo => 'init_obj_foo', bar => 'init_obj_bar', max => 'init_obj_max',
+ my_comp => { one => 'init_obj_one', two => 'init_obj_two' } };
+
+$item = undef;
+$form->process( item => $item, init_object => $init_obj, params => {} );
+is( $form->field('foo')->fif, 'init_obj_foo' );
+is( $form->field('bar')->fif, 'init_obj_bar' );
+is( $form->field('max')->fif, 'init_obj_max' );
+is( $form->field('my_comp.one')->fif, 'init_obj_one', 'init_obj value pulled in for compound' );
+
+$item = { foo => 'item_foo', bar => 'item_bar' };
+$form->process( item => $item, init_object => $init_obj, params => {} );
+is( $form->field('foo')->fif, 'item_foo' );
+is( $form->field('bar')->fif, 'item_bar' );
+is( $form->field('max')->fif, 'init_obj_max' );
+is( $form->field('my_comp.one')->fif, 'init_obj_one', 'init_obj value pulled in for compound' );
+
+done_testing;
Please sign in to comment.
Something went wrong with that request. Please try again.