Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select.t =================================================================== --- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select.t (revision 1493) +++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select.t (working copy) @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 5; +use Test::More tests => 13; use HTML::FormFu; use lib 't/lib'; @@ -39,6 +39,9 @@ # band 3 - not used $schema->resultset('Band')->create({ band => 'the kinks' }); + # band 4 - not used + $schema->resultset('Band')->create({ band => 'the hoorays' }); + # band 1 $u2->add_to_bands($band1); } @@ -75,3 +78,66 @@ is( $id[1], 3 ); } +# additive + +$form = HTML::FormFu->new; + +$form->load_config_file('t/update/many_to_many_select_additive.yml'); + +$form->stash->{schema} = $schema; + +{ + $form->process( { + id => 2, + name => 'Paul McCartney', + bands => 2, + } ); + + ok( $form->submitted_and_valid ); + + my $row = $schema->resultset('User')->find(2); + + $form->model->update($row); +} + +{ + my $row = $schema->resultset('User')->find(2); + + is( $row->name, 'Paul McCartney' ); + + my @bands = $row->bands->all; + + is( scalar @bands, 3 ); + + my @id = sort map { $_->id } @bands; + + is_deeply( \@id, [qw(1 2 3)] ); +} + +{ + $form->process( { + id => 2, + name => 'Paul McCartney', + bands => [qw(1 2 3 4)], + } ); + + ok( $form->submitted_and_valid ); + + my $row = $schema->resultset('User')->find(2); + + $form->model->update($row); +} + +{ + my $row = $schema->resultset('User')->find(2); + + is( $row->name, 'Paul McCartney' ); + + my @bands = $row->bands->all; + + is( scalar @bands, 4 ); + + my @id = sort map { $_->id } @bands; + + is_deeply( \@id, [qw(1 2 3 4)] ); +} \ No newline at end of file Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select_additive.yml =================================================================== --- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select_additive.yml (revision 0) +++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/many_to_many_select_additive.yml (revision 0) @@ -0,0 +1,19 @@ +--- +auto_fieldset: 1 + +elements: + - type: Hidden + name: id + + - type: Text + name: name + + - type: Select + name: bands + multiple: 1 + model_config: + additive: 1 + options_from_model: 0 + + - type: Submit + name: submit Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm =================================================================== --- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm (revision 1493) +++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm (working copy) @@ -61,7 +61,7 @@ my ( $self, $base, $attrs ) = @_; $attrs = $attrs ? _compatible_attrs($attrs) : {}; - + my $form = $base->form; my $resultset = _get_resultset( $base, $form, $attrs ); my $source = $resultset->result_source; @@ -121,14 +121,13 @@ if ( defined $schema ) { my $rs_name = $attrs->{resultset} || ucfirst $base->name; - return $schema->resultset($rs_name); } elsif ( defined $context && defined $attrs->{model} ) { my $model = $context->model( $attrs->{model} ); - if ( defined( my $rs = $attrs->{resultset} ) ) { + if ( defined( my $rs = $attrs->{resultset} || ucfirst $base->name ) ) { $model = $model->resultset( $rs ); } @@ -817,7 +816,7 @@ sub _save_multi_value_fields_many_to_many { my ( $base, $dbic, $form, $attrs, $rels, $cols ) = @_; - + my @fields = grep { ( defined $attrs->{nested_base} && defined $_->parent->nested_name ) ? $_->parent->nested_name eq $attrs->{nested_base} @@ -843,12 +842,13 @@ my @values = $form->param_list($nested_name); my @rows; - if (@values) { - my $config = _compatible_config($field); + my $config = _compatible_config($field); - my ($pk) = $config->{default_column} - || $related->result_source->primary_columns; + my ($pk) = $config->{default_column} + || $related->result_source->primary_columns; + if (@values) { + $pk = "me.$pk" unless $pk =~ /\./; @rows = $related->result_source->resultset->search( { @@ -856,9 +856,23 @@ $pk => { -in => \@values } } )->all; } - my $set_method = "set_$name"; - - $dbic->$set_method( \@rows ); + if($config->{additive}) { + + $pk =~ s/^.*\.//; + + my $set_method = "add_to_$name"; + + my @current = map { $_->$pk } $related->all; + + foreach my $row ( @rows ) { + next if grep { $_ eq $row->id } @current; + $dbic->$set_method($row); + } + } else { + my $set_method = "set_$name"; + + $dbic->$set_method( \@rows ); + } } } } @@ -1356,7 +1370,23 @@ model_config: default_column: foo +The default implementation will first remove all related objects and set the +new ones (see L). +If you want to add the selected objects to the current set of objects +set C in the C. + --- + element: + - type: Checkboxgroup + name: authors + model_config: + additive: 1 + options_from_model: 0 + +( is set to C<0> because this L will try to fetch +all objects from the result class C if C is specified +without a C attribute.) + =head1 COMMON ARGUMENTS The following items are supported in the optional C hash-ref argument