File Coverage

blib/lib/Data/MuForm.pm
Criterion Covered Total %
statement 237 278 85.2
branch 55 80 68.7
condition 19 29 65.5
subroutine 71 83 85.5
pod 10 72 13.8
total 392 542 72.3


line stmt bran cond sub pod time code
1             package Data::MuForm;
2             # ABSTRACT: Data validator and form processor
3              
4 82     82   152143 use Moo;
  82         25585  
  82         441  
5 82     82   21192 use Data::MuForm::Meta;
  82         105  
  82         474  
6              
7             with 'Data::MuForm::Model';
8             with 'Data::MuForm::Fields';
9             with 'Data::MuForm::Common';
10              
11 82     82   48879 use Types::Standard -types;
  82         3047198  
  82         821  
12 82     82   253973 use Class::Load ('load_optional_class');
  82         805811  
  82         4595  
13 82     82   26095 use Data::Clone ('data_clone');
  82         68327  
  82         4039  
14 82     82   28817 use Data::MuForm::Params;
  82         399  
  82         2290  
15 82     82   30723 use Data::MuForm::Localizer;
  82         438  
  82         3298  
16 82     82   37385 use MooX::Aliases;
  82         191309  
  82         447  
17 82     82   46141 use Data::MuForm::Merge ('merge');
  82         135  
  82         203813  
18              
19             our $VERSION = '0.04';
20              
21              
22             has 'name' => ( is => 'ro', builder => 'build_name');
23             sub build_name {
24 110     110 0 2033 my $self = shift;
25 110         244 my $class = ref $self;
26 110         504 my ( $name ) = ( $class =~ /.*::(.*)$/ );
27 110   66     354 $name ||= $class;
28 110         1551 return $name;
29             }
30             has 'id' => ( is => 'ro', lazy => 1, builder => 'build_id' );
31 1     1 0 314 sub build_id { $_[0]->name }
32             has 'submitted' => ( is => 'rw', default => undef ); # three values: 0, 1, undef
33             has 'processed' => ( is => 'rw', default => 0 );
34             #has 'no_init_process' => ( is => 'rw', default => 0 );
35              
36             has 'ran_validation' => ( is => 'rw', default => 0 );
37             has '_params' => ( is => 'rw', isa => HashRef, default => sub {{}}, alias => 'data' );
38 71     71 0 143 sub clear_params { $_[0]->{_params} = {} }
39 171     171 0 239 sub has_params { my $self = shift; return scalar keys %{$self->{_params}}; }
  171         185  
  171         1210  
40             sub params {
41 316     316 1 373 my ( $self, $params ) = @_;
42 316 100       620 if ( $params ) {
43 146         495 $params = $self->munge_params($params);
44 146         274 $self->{_params} = $params;
45             }
46 316         1368 return $self->{_params};
47             }
48             has 'field_prefix' => ( is => 'rw' );
49              
50             has 'form_meta_fields' => ( is => 'rw', isa => ArrayRef, default => sub {[]} );
51             has 'index' => ( is => 'rw', isa => HashRef, default => sub {{}} );
52 571     571 0 748 sub add_to_index { my ( $self, $field_name, $field ) = @_; $self->{index}->{$field_name} = $field; }
  571         1676  
53 4497     4497 1 24395 sub form { shift }
54 591     591 0 1798 sub is_form {1}
55       65 0   sub parent { }
56             has 'ctx' => ( is => 'rw', weak_ref => 1 );
57             # init_values can be a blessed object or a hashref
58             has 'init_values' => ( is => 'rw', alias => 'init_object' );
59 71     71 0 140 sub clear_init_values { $_[0]->{init_values} = undef }
60             sub has_init_values {
61 23     23 0 1240 my $self = shift;
62 23         43 my $init_obj = $self->init_values;
63 23 100       89 return 0 unless defined $init_obj;
64 7 50 33     35 return 0 if ref $init_obj eq 'HASH' and ! scalar keys %$init_obj;
65 7         24 return 1;
66             }
67             has 'fill_from_object_source' => ( is => 'rw', );
68             has 'active' => ( is => 'rw', clearer => 'clear_active', predicate => 'has_active' );
69             has 'inactive' => ( is => 'rw', clearer => 'clear_inactive', predicate => 'has_inactive' );
70 1468     1468 0 6962 sub full_name { '' }
71 15     15 0 307 sub full_accessor { '' }
72 58     58 1 9685 sub fif { shift->fields_fif(@_) }
73              
74             has '_repeatable_fields' => (
75             is => 'rw',
76             default => sub {[]},
77             );
78             sub add_repeatable_field {
79 35     35 0 231 my ( $self, $field ) = @_;
80 35         51 push @{$self->_repeatable_fields}, $field;
  35         179  
81             }
82             sub has_repeatable_fields {
83 64     64 0 103 my ( $self, $field ) = @_;
84 64         72 return scalar @{$self->_repeatable_fields};
  64         509  
85             }
86             sub all_repeatable_fields {
87 3     3 0 13 my $self = shift;
88 3         4 return @{$self->_repeatable_fields};
  3         45  
89             }
90              
91             #========= Rendering ==========
92             has 'http_method' => ( is => 'ro', default => 'post' );
93             has 'action' => ( is => 'rw' );
94             has 'enctype' => ( is => 'rw' );
95             has 'renderer_class' => ( is => 'ro', builder => 'build_renderer_class' );
96 133     133 0 3843 sub build_renderer_class { 'Data::MuForm::Renderer::Base' }
97             has 'renderer' => ( is => 'rw', lazy => 1, builder => 'build_renderer' );
98             sub build_renderer {
99 133     133 0 24734 my $self = shift;
100 133 50       1138 my $renderer_class = load_optional_class($self->renderer_class) ? $self->renderer_class : 'Data::MuForm::Renderer::Base';
101             my $renderer = $renderer_class->new(
102             localizer => $self->localizer,
103             form => $self->form,
104 133         9906 %{$self->renderer_args},
  133         1848  
105             );
106 133         677 return $renderer;
107             }
108             has 'renderer_args' => ( is => 'ro', isa => HashRef, builder => 'build_renderer_args' );
109 130     130 0 3325 sub build_renderer_args {{}}
110             has 'render_args' => ( is => 'rw', lazy => 1, isa => HashRef, builder => 'build_render_args' );
111 7     7 0 3180 sub build_render_args {{}}
112             sub base_render_args {
113 7     7 0 12 my $self = shift;
114 7   50     118 my $args = {
115             name => $self->name,
116             id => $self->name,
117             form_errors => $self->form_errors || [],
118             form_attr => {
119             method => $self->http_method,
120             }
121             };
122 7 50       2626 $args->{form_attr}->{action} = $self->action if $self->action;
123 7 50       36 $args->{form_attr}->{enctype} = $self->enctype if $self->enctype;
124 7         75 return $args;
125             }
126              
127              
128             #========= Errors ==========
129             has 'form_errors' => ( is => 'rw', isa => ArrayRef, default => sub {[]} );
130 71     71 0 151 sub clear_form_errors { $_[0]->{form_errors} = []; }
131 5     5 0 6 sub all_form_errors { return @{$_[0]->form_errors}; }
  5         40  
132 5     5 0 998 sub has_form_errors { scalar @{$_[0]->form_errors} }
  5         51  
133 7     7 0 199 sub num_form_errors { scalar @{$_[0]->form_errors} }
  7         90  
134 0     0 0 0 sub push_form_error { push @{$_[0]->form_errors}, $_[1] }
  0         0  
135             sub add_form_error {
136 0     0 0 0 my ( $self, @message ) = @_;
137 0         0 my $out;
138 0 0       0 if ( $message[0] !~ /{/ ) {
139 0         0 $out = $self->localizer->loc_($message[0]);
140             }
141             else {
142 0         0 $out = $self->localizer->loc_x(@message);
143             }
144 0         0 return $self->push_form_error($out);
145             }
146              
147             sub has_errors {
148 16     16 0 1490 my $self = shift;
149 16   66     50 return $self->has_error_fields || $self->has_form_errors;
150             }
151             sub num_errors {
152 7     7 0 1483 my $self = shift;
153 7         59 return $self->num_error_fields + $self->num_form_errors;
154             }
155 0     0 0 0 sub get_errors { shift->errors }
156              
157             sub all_errors {
158 5     5 0 387 my $self = shift;
159 5         44 my @errors = $self->all_form_errors;
160 5         2139 push @errors, map { $_->all_errors } $self->all_error_fields;
  11         155  
161 5         38 return @errors;
162             }
163 2     2 1 271 sub errors { [$_[0]->all_errors] }
164              
165             sub errors_by_id {
166 1     1 0 1 my $self = shift;
167 1         2 my %errors;
168 1         7 $errors{$_->id} = [$_->all_errors] for $self->all_error_fields;
169 1         6 return \%errors;
170             }
171              
172             sub errors_by_name {
173 1     1 0 1 my $self = shift;
174 1         2 my %errors;
175 1         3 $errors{$_->prefixed_name} = [$_->all_errors] for $self->all_error_fields;
176 1         20 return \%errors;
177             }
178              
179             #========= Localization ==========
180              
181             has 'language' => ( is => 'rw', builder => 'build_language' );
182 133     133 0 4056 sub build_language { 'en' }
183             has 'localizer' => ( is => 'rw', lazy => 1, builder => 'build_localizer' );
184             sub build_localizer {
185 133     133 0 25496 my $self = shift;
186 133         2606 return Data::MuForm::Localizer->new(
187             language => $self->language,
188             );
189             }
190              
191             #========= Messages ==========
192             has 'messages' => ( is => 'rw', isa => HashRef, builder => 'build_messages' );
193 132     132 0 2566 sub build_messages {{}}
194 1     1   520 sub _get_form_message { my ($self, $msgname) = @_; return $self->messages->{$msgname}; }
  1         19  
195 38     38   320 sub _has_form_message { my ($self, $msgname) = @_; return exists $self->messages->{$msgname}; }
  38         420  
196 0     0 0 0 sub set_message { my ( $self, $msgname, $msg) = @_; $self->messages->{$msgname} = $msg; }
  0         0  
197             my $class_messages = {};
198             sub get_class_messages {
199 0     0 0 0 return $class_messages;
200             }
201             sub get_message {
202 0     0 0 0 my ( $self, $msg ) = @_;
203 0 0       0 return $self->_get_form_message($msg) if $self->_has_form_message($msg);
204 0         0 return $self->get_class_messages->{$msg};
205             }
206             sub all_messages {
207 0     0 0 0 my $self = shift;
208 0         0 return { %{$self->get_class_messages}, %{$self->messages} };
  0         0  
  0         0  
209             }
210              
211              
212             #========= Methods ==========
213             sub BUILD {
214 133     133 0 715 my $self = shift;
215              
216             # instantiate
217 133         1253 $self->localizer;
218 133         59295 $self->renderer;
219 133         981 $self->build_fields;
220 132         1668 $self->after_build_fields;
221             # put various defaults into fields. Should this happen?
222             # it will be re-done on the first process call
223 132         2544 $self->fill_values;
224             }
225              
226             sub process {
227 170     170 1 54091 my $self = shift;
228              
229 170 100       1123 $self->clear if $self->processed;
230 170         701 $self->setup(@_);
231 170         619 $self->after_setup;
232 170 100       726 $self->validate_form if $self->submitted;
233              
234 170 100       570 $self->update_model if ( $self->validated );
235 170 100       1190 $self->after_update_model if ( $self->validated );
236              
237 170         1385 $self->processed(1);
238 170         287 return $self->validated;
239             }
240              
241             sub check {
242 0     0 1 0 my $self = shift;
243 0 0       0 $self->clear if $self->processed;
244 0         0 $self->setup(@_);
245 0         0 $self->after_setup;
246 0 0       0 $self->validate_form if $self->submitted;
247 0         0 $self->processed(1);
248 0         0 return $self->check_result;
249             }
250              
251             sub check_result {
252 0     0 0 0 my $self = shift;
253 0         0 return $self->validated;
254             }
255              
256             sub clear {
257 71     71 0 98 my $self = shift;
258 71         253 $self->clear_params;
259 71         353 $self->clear_filled_from;
260 71         11481 $self->submitted(undef);
261 71         209 $self->model(undef);
262 71         396 $self->clear_init_values;
263 71         331 $self->fill_from_object_source(undef);
264 71         780 $self->ctx(undef);
265 71         12381 $self->processed(0);
266 71         182 $self->ran_validation(0);
267              
268             # this will recursively clear field data
269 71         322 $self->clear_data;
270 71         3572 $self->clear_form_errors;
271 71         186 $self->clear_error_fields;
272             }
273              
274              
275             sub setup {
276 170     170 1 325 my ( $self, @args ) = @_;
277              
278 170 100       1042 if ( @args == 1 ) {
    100          
279 38         143 $self->params( $args[0] );
280             }
281             elsif ( @args > 1 ) {
282 116         242 my $hashref = {@args};
283 116         157 while ( my ( $key, $value ) = each %{$hashref} ) {
  280         1672  
284 164 50       724 warn "invalid attribute '$key' passed to setup_form"
285             unless $self->can($key);
286 164         498 $self->$key($value);
287             }
288             }
289             # set_active
290 170         678 $self->set_active;
291              
292             # customization hook
293 170         836 $self->in_setup;
294              
295             # set the submitted flag
296 170 100 100     510 $self->submitted(1) if ( $self->has_params && ! defined $self->submitted );
297              
298             # fill the 'value' attributes from model, init_values or fields
299 170         377 $self->fill_values;
300              
301             # fill in the input attribute
302 170         3010 my $params = data_clone( $self->params );
303 170 100       594 if ( $self->submitted ) {
304 105         588 $self->fill_from_params($params, 1 );
305             # if the params submitted don't match fields, it shouldn't count as 'submitted'
306 105 100       106 if ( ! scalar keys %{$self->input} ) {
  105         575  
307 2         8 $self->submitted(0);
308             }
309             }
310              
311             }
312              
313             sub fill_values {
314 302     302 0 362 my $self = shift;
315              
316             # these fill the 'value' attributes
317 302 100 66     2835 if ( $self->model && $self->use_model_for_defaults ) {
    100          
    100          
318 9         32 $self->fill_from_object_source('model');
319 9         23 $self->fill_from_object($self->model);
320             }
321             elsif ( $self->init_values ) {
322 41         927 $self->fill_from_object_source('init_values');
323 41         196 $self->fill_from_object($self->init_values );
324             }
325             elsif ( !$self->submitted ) {
326             # no initial object. empty form must be initialized
327 157         1654 $self->fill_from_fields;
328             }
329             }
330              
331       170 0   sub in_setup { }
332       170 0   sub after_setup { }
333       129 0   sub after_build_fields { }
334              
335             sub update_model {
336 62     62 0 14826 my $self = shift;
337             }
338              
339              
340             sub munge_params {
341 146     146 0 178 my ( $self, $params, $attr ) = @_;
342              
343 146         2072 my $_fix_params = Data::MuForm::Params->new;
344 146         40930 my $new_params = $_fix_params->expand_hash($params);
345 146 50       1570 if ( $self->field_prefix ) {
346 0         0 $new_params = $new_params->{ $self->field_prefix };
347             }
348 146 50       342 $new_params = {} if !defined $new_params;
349 146         1381 return $new_params;
350             }
351              
352             sub set_active {
353 170     170 0 214 my $self = shift;
354 170 100       704 if( $self->has_active ) {
355 1         2 foreach my $fname (@{$self->active}) {
  1         3  
356 1         6 my $field = $self->field($fname);
357 1 50       6 if ( $field ) {
358 1         6 $field->_active(1);
359             }
360             else {
361 0         0 warn "field $fname not found to set active";
362             }
363             }
364 1         5 $self->clear_active;
365             }
366 170 100       1074 if( $self->has_inactive ) {
367 2         1 foreach my $fname (@{$self->inactive}) {
  2         8  
368 2         7 my $field = $self->field($fname);
369 2 50       11 if ( $field ) {
370 2         7 $field->_active(0);
371             }
372             else {
373 0         0 warn "field $fname not found to set inactive";
374             }
375             }
376 2         25 $self->clear_inactive;
377             }
378             }
379              
380             #====================================================================
381             # Validation
382             #====================================================================
383              
384             sub validate_form {
385 103     103 0 139 my $self = shift;
386              
387 103         440 $self->fields_validate;
388 103         403 $self->validate; # hook
389 103         417 $self->validate_model; # hook
390 103         504 $self->fields_set_value;
391 103         253 $self->submitted(undef);
392 103         403 $self->ran_validation(1);
393             }
394              
395             # hook for child forms
396       98 1   sub validate { }
397              
398             # hook for model validation
399       103 0   sub validate_model { }
400              
401 567   100 567 1 2159 sub validated { my $self = shift; return $self->ran_validation && ! $self->has_error_fields; }
  567         2125  
402              
403       157 0   sub get_default_value { }
404              
405             sub transform_and_set_input {
406 105     105 0 146 my ($self, $input) = @_;
407 105         436 $self->input($input);
408             }
409              
410             sub get_result {
411 1     1 0 1 my $self = shift;
412 1         13 my $result = {
413             method => $self->http_method,
414             action => $self->action,
415             name => $self->name,
416             id => $self->id,
417             submitted => $self->submitted,
418             validated => $self->validated,
419             };
420 1 50       6 $result->{form_errors} = $self->form_errors if $self->has_form_errors;
421 1 50       435 $result->{errors} = $self->errors if $self->has_errors;
422 1         10 return $result;
423             }
424              
425 1     1 0 377 sub results { shift->fields_get_results }
426              
427             sub add_field {
428 2     2 1 12 my ( $self, %field_attr ) = @_;
429 2         5 my $field = $self->_make_field( \%field_attr );
430             # make it the last field.
431 2 100       5 unless ( exists $field_attr{order} ) {
432 1         14 my $order = $field->parent->_get_highest_field_order;
433 1         3 $field->order($order + 5);
434             }
435 2         5 return $field;
436             }
437              
438             sub after_update_model {
439 64     64 0 1837 my $self = shift;
440             # This an attempt to reload the repeatable
441             # relationships after the database is updated, so that we get the
442             # primary keys of the repeatable elements. Otherwise, if a form
443             # is re-presented, repeatable elements without primary keys may
444             # be created again. There is no reliable way to connect up
445             # existing repeatable elements with their db-created primary keys.
446 64 100 100     297 if ( $self->has_repeatable_fields && $self->model ) {
447 2         78 foreach my $field ( $self->all_repeatable_fields ) {
448 4 50       11 next unless $field->is_active;
449             # Check to see if there are any repeatable subfields with
450             # null primary keys, so we can skip reloading for the case
451             # where all repeatables have primary keys.
452 4         5 my $needs_reload = 0;
453 4         13 foreach my $sub_field ( $field->all_fields ) {
454 2 100 66     14 if ( $sub_field->is_compound && $sub_field->has_primary_key ) {
455 1         2 foreach my $pk_field ( @{ $sub_field->primary_key } ) {
  1         35  
456 1 50       15 $needs_reload++ unless $pk_field->fif;
457             }
458 1 50       4 last if $needs_reload;
459             }
460             }
461 4 100       10 next unless $needs_reload;
462 1         6 my @names = split( /\./, $field->full_name );
463 1         4 my $rep_model = $self->find_sub_obj( $self->model, \@names );
464             # $rep_model is a single row or an array of rows or undef
465             # If we found a database model for the repeatable, initialize
466             # with 'fill_from_object'
467 1 50       5 if ( ref $rep_model ) {
468 1         29 my $parent = $field->parent;
469 1         8 $field->init_state;
470 1         53 $field->fill_from_object( $rep_model );
471             }
472             }
473             }
474             }
475              
476             # model for render_hook in forms to modify render_args for rendering
477             sub render_hook {
478 213     213 0 404 my ( $self, $renderer, $rargs ) = @_;
479             }
480              
481             sub get_render_args {
482 7     7 0 24 my ( $self, %args ) = @_;
483 7         42 my $render_args = merge( $self->base_render_args, $self->render_args );
484 7         28 $render_args = merge( $render_args, \%args );
485 7         17 return $render_args;
486             }
487              
488             sub render {
489 6     6 0 508 my ( $self, $rargs ) = @_;
490 6         41 my $render_args = $self->get_render_args(%$rargs, rendering => 'form');
491 6         117 return $self->renderer->render_form($render_args, $self->sorted_fields);
492             }
493              
494             sub render_start {
495 1     1 0 376 my ( $self, $rargs ) = @_;
496 1         6 my $render_args = $self->get_render_args( form_attr => $rargs, rendering => 'form_start');
497 1         22 return $self->renderer->render_start($render_args);
498             }
499              
500             sub render_end {
501 0     0 0   my ( $self, $rargs ) = @_;
502             # is there any need for attributes on a form end tag? never seen any...
503 0           my $render_args = $self->get_render_args(rendering => 'form_end');
504 0           return $self->renderer->render_end($render_args);
505             }
506              
507             sub render_errors {
508 0     0 0   my ( $self, $rargs ) = @_;
509             # we're not doing 'form_error_attr'. only processing 'error_tag' and 'error_class'
510 0           my $render_args = $self->get_render_args( %$rargs, rendering => 'form_errors');
511 0           return $self->renderer->render_form_errors($render_args);
512             }
513              
514             # just for top level fields
515             sub render_hidden_fields {
516 0     0 0   my $self = shift;
517 0           foreach my $field ( $self->all_sorted_fields ) {
518 0 0 0       if ( $field->type eq 'Hidden' && $field->has_value ) {
519 0           $field->render_element;
520             }
521             }
522             }
523              
524             1;
525              
526             __END__
527              
528             =pod
529              
530             =encoding UTF-8
531              
532             =head1 NAME
533              
534             Data::MuForm - Data validator and form processor
535              
536             =head1 VERSION
537              
538             version 0.04
539              
540             =head1 SYNOPSIS
541              
542             Moo conversion of HTML::FormHandler, with more emphasis on data
543             validation and a new way of rendering. The core behavior is basically
544             the same as FormHandler, but some names have been changed, some
545             functionality removed, some added. It will be necessary to change
546             your forms to convert to MuForm, but it shouldn't be difficult.
547              
548             See the manual at L<Data::MuForm::Manual>, and in particular
549             L<Data::MuForm::Manual::FormHandlerDiff> if you're already using
550             FormHandler.
551              
552             my $validator = MyApp::Form::Test->new;
553             $validator->check( data => $params );
554             or
555             my $form = MyApp::Form::User->new;
556             $form->process( model => $row, params => $params );
557             my $rendered_form = $form->render;
558             if( $form->validated ) {
559             # perform validated form actions
560             }
561             else {
562             # perform non-validated actions
563             }
564              
565             An example of a custom form class:
566              
567             package MyApp::Form::User;
568             use Moo;
569             use Data::MuForm::Meta;
570             extends 'Data::MuForm';
571              
572             has_field 'name' => ( type => 'Text' );
573             has_field 'age' => ( type => 'Integer', apply => [ MinimumAge ] );
574             has_field 'hobbies' => ( type => 'Multiple' );
575             has_field 'address' => ( type => 'Compound' );
576             has_field 'address.city' => ( type => 'Text' );
577             has_field 'address.state' => ( type => 'Select' );
578             has_field 'email' => ( type => 'Email' );
579              
580             A dynamic form - one that does not use a custom form class - may be
581             created using the 'field_list' attribute to set fields:
582              
583             my $validator = Data::MuForm->new(
584             name => 'login_form',
585             field_list => [
586             'username' => {
587             type => 'Text',
588             apply => [ { check => qr/^[0-9a-z]*\z/,
589             message => 'Contains invalid characters' } ],
590             },
591             'password' => { apply => [ Password ] },
592             ],
593             );
594              
595             =head1 DESCRIPTION
596              
597             This documentation is mainly of Data::MuForm class attributes and methods.
598             For general-purpose documentation see L<Data::MuForm::Manual>.
599              
600             =head1 NAME
601              
602             Data::MuForm
603              
604             =head1 ATTRIBUTES and METHODS
605              
606             =head2 Creating a form with 'new'
607              
608             The new constructor takes name/value pairs:
609              
610             MyForm->new( action => $action );
611              
612             No attributes are required on new. Normally you would pass in persistent
613             attributes on 'new' (such as 'schema') and request/process related attributes on 'process'.
614              
615             The form's fields will be built from the form definitions on new.
616              
617             The 'field_list' is passed in on 'new' because fields are build at construction time.
618             It can also be a method in the form class.
619              
620             field_list - an array of field definitions
621              
622             =head2 process & check
623              
624             Data to be validated/processed:
625              
626             data $validator->check( data => {} );
627             params $form->process( params => {} );
628              
629             The 'init_values' hashref can be passed in, but can also be set in the form class:
630              
631             init_values - a hashref or object to provide initial values
632              
633             Passed in on process with a DBIC model MuForm class:
634              
635             model - database row object
636              
637             See the model class for more information about 'model', 'model_id',
638             'model_class', and 'schema' (for the DBIC model).
639             L<Data::MuForm::Model::DBIC>.
640              
641             =head2 Processing
642              
643             =head3 check
644              
645             Use the 'check' method to perform validation on your data:
646              
647             my $result = $validator->check( data => { ... } );
648              
649             The 'result' returned from 'check' is $form->validated, but you can
650             override the 'check_result' method in the form to return data in
651             whatever format you wish.
652              
653             =head3 process
654              
655             Call the 'process' method on your form to perform validation and
656             update. A database form must have either a model (row object) or
657             a schema, model_id (row primary key), and model_class (usually set in the form).
658             A non-database form requires only parameters.
659              
660             $form->process( model => $book, params => $c->req->parameters );
661             $form->process( model_id => $model_id,
662             schema => $schema, params => $c->req->parameters );
663             $form->process( params => $c->req->parameters );
664              
665             This process method returns the 'validated' flag (C<< $form->validated >>).
666             If it is a database form and the form validates, the database row
667             will be updated.
668              
669             After the form has been processed, you can get a parameter hashref suitable
670             for using to fill in the form from C<< $form->fif >>.
671             A hash of inflated values (that would be used to update the database for
672             a database form) can be retrieved with C<< $form->value >>.
673              
674             If you don't want to update the database, you can use the 'check' method instead.
675              
676             =head3 params
677              
678             Parameters are passed in when you call 'process'.
679             HFH gets data to validate and store in the database from the params hash.
680             If the params hash is empty, no validation is done, so it is not necessary
681             to check for POST before calling C<< $form->process >>. (Although see
682             the 'posted' option for complications.)
683              
684             Params can either be in the form of CGI/HTTP style params:
685              
686             {
687             user_name => "Joe Smith",
688             occupation => "Programmer",
689             'addresses.0.street' => "999 Main Street",
690             'addresses.0.city' => "Podunk",
691             'addresses.0.country' => "UT",
692             'addresses.0.address_id' => "1",
693             'addresses.1.street' => "333 Valencia Street",
694             'addresses.1.city' => "San Francisco",
695             'addresses.1.country' => "UT",
696             'addresses.1.address_id' => "2",
697             }
698              
699             or as structured data in the form of hashes and lists:
700              
701             {
702             addresses => [
703             {
704             city => 'Middle City',
705             country => 'GK',
706             address_id => 1,
707             street => '101 Main St',
708             },
709             {
710             city => 'DownTown',
711             country => 'UT',
712             address_id => 2,
713             street => '99 Elm St',
714             },
715             ],
716             'occupation' => 'management',
717             'user_name' => 'jdoe',
718             }
719              
720             CGI style parameters will be converted to hashes and lists for HFH to
721             operate on.
722              
723             =head3 submitted
724              
725             Note that MuForm by default uses empty params as a signal that the
726             form has not actually been submitted, and so will not attempt to validate
727             a form with empty params. Most of the time this works OK, but if you
728             have a small form with only the controls that do not return a post
729             parameter if unselected (checkboxes and select lists), then the form
730             will not be validated if everything is unselected. For this case you
731             can either add a hidden field as an 'indicator', or use the 'submitted' flag:
732              
733             $form->process( submitted => ($c->req->method eq 'POST'), params => ... );
734              
735             The 'submitted' flag also works to prevent validation from being performed
736             if there are extra params in the params hash and it is not a 'POST' request.
737              
738             =head2 Getting data out
739              
740             =head3 fif (fill in form)
741              
742             If you don't use MuForm rendering and want to fill your form values in
743             using some other method (such as with HTML::FillInForm or using a template)
744             this returns a hash of values that are equivalent to params which you may
745             use to fill in your form.
746              
747             The fif value for a 'title' field in a TT form:
748              
749             [% form.fif.title %]
750              
751             Or you can use the 'fif' method on individual fields:
752              
753             [% form.field('title').fif %]
754              
755             If you use MuForm to render your forms or field you probably won't use
756             these methods.
757              
758             =head3 value
759              
760             Returns a hashref of all field values. Useful for non-database forms, or if
761             you want to update the database yourself. The 'fif' method returns
762             a hashref with the field names for the keys and the field's 'fif' for the
763             values; 'value' returns a hashref with the field accessors for the keys, and the
764             field's 'value' (possibly inflated) for the values.
765              
766             Forms containing arrays to be processed with L<Data::MuForm::Field::Repeatable>
767             will have parameters with dots and numbers, like 'addresses.0.city', while the
768             values hash will transform the fields with numbers to arrays.
769              
770             =head2 Accessing and setting up fields
771              
772             Fields are declared with a number of attributes which are defined in
773             L<Data::MuForm::Field>. If you want additional attributes you can
774             define your own field classes (or apply a role to a field class - see
775             L<Data::MuForm::Manual::Cookbook>). The field 'type' (used in field
776             definitions) is the short class name of the field class, used when
777             searching the 'field_namespace' for the field class.
778              
779             =head3 has_field
780              
781             The most common way of declaring fields is the 'has_field' syntax.
782             Using the 'has_field' syntax sugar requires C< use Data::MuForm::Meta; >.
783             See L<Data::MuForm::Manual::Intro>
784              
785             use Moo;
786             use Data::MuForm::Meta;
787             has_field 'field_name' => ( type => 'FieldClass', .... );
788              
789             =head3 field_list
790              
791             A 'field_list' is an array of field definitions which can be used as an
792             alternative to 'has_field' in small, dynamic forms to create fields.
793              
794             field_list => [
795             field_one => {
796             type => 'Text',
797             required => 1
798             },
799             field_two => 'Text,
800             ]
801              
802             The field_list array takes elements which are either a field_name key
803             pointing to a 'type' string or a field_name key pointing to a
804             hashref of field attributes. You can also provide an array of
805             hashref elements with the name as an additional attribute.
806             The field list can be set inside a form class, when you want to
807             add fields to the form depending on some other state, although
808             you can also create all the fields and set some of them inactive.
809              
810             sub field_list {
811             my $self = shift;
812             my $fields = $self->schema->resultset('SomeTable')->
813             search({user_id => $self->user_id, .... });
814             my @field_list;
815             while ( my $field = $fields->next )
816             {
817             < create field list >
818             }
819             return \@field_list;
820             }
821              
822             =head2 add_field
823              
824             You can add an additional field with $form->add_field.
825              
826             my $order = $form->field('foo')->order + 1;
827             $form->add_field(
828             name => 'my_cb',
829             type => 'Checkbox',
830             order => $order,
831             );
832              
833             It will be ordered as the last field unless you set the 'order'
834             attribute. Form fields are automatically ordered by 5 (i.e. 5, 10, 15, etc).
835              
836             =head3 active/inactive
837              
838             A field can be marked 'inactive' and set to active at process time
839             by specifying the field name in the 'active' array:
840              
841             has_field 'foo' => ( type => 'Text', inactive => 1 );
842             ...
843             my $form = MyApp::Form->new;
844             $form->process( active => ['foo'] );
845              
846             Or a field can be a normal active field and set to inactive at process
847             time:
848              
849             has_field 'bar';
850             ...
851             my $form = MyApp::Form->new;
852             $form->process( inactive => ['foo'] );
853              
854             Fields specified as active/inactive on 'process' will have the flag
855             flag cleared when the form is cleared (on the next process/check call).
856              
857             The 'sorted_fields' method returns only active fields, sorted according to the
858             'order' attribute. The 'fields' method returns all fields.
859              
860             foreach my $field ( $self->all_sorted_fields ) { ... }
861              
862             You can test whether a field is active by using the field 'is_active' and 'is_inactive'
863             methods.
864              
865             =head3 field_namespace
866              
867             Use to look for field during form construction. If a field is not found
868             with the field_namespace (or Data::MuForm/Data::MuFormX),
869             the 'type' must start with a '+' and be the complete package name.
870              
871             =head3 fields
872              
873             The array of fields, objects of L<Data::MuForm::Field> or its subclasses.
874             A compound field will itself have an array of fields,
875             so this is a tree structure.
876              
877             =head3 sorted_fields
878              
879             Returns those fields from the fields array which are currently active, ordered
880             by the 'order' attribute. This is the method that returns the fields that are
881             looped through when rendering.
882              
883             =head3 field($name), subfield($name)
884              
885             'field' is the method that is usually called to access a field:
886              
887             my $title = $form->field('title')->value;
888             [% f = form.field('title') %]
889              
890             my $city = $form->field('addresses.0.city')->value;
891              
892             Since fields are searched for using the form as a base, if you want to find
893             a sub field in a compound field method, the 'subfield' method may be more
894             useful, since you can search starting at the current field. The 'chained'
895             method also works:
896              
897             -- in a compound field --
898             $self->field('media.caption'); # fails
899             $self->field('media')->field('caption'); # works
900             $self->subfield('media.caption'); # works
901              
902             =head3 build_field_id
903              
904             Create a 'build_field_id' sub in the form class to use a common method for
905             constructing field ids.
906              
907             sub build_field_id {
908             my ( $self, $field ) = @_;
909             return $field->name . '_' . $self->id;
910             }
911              
912             =head2 Constraints and validation
913              
914             Most validation is performed on a per-field basis, and there are a number
915             of different places in which validation can be performed.
916              
917             See also L<Data::MuForm::Manual::Validation>.
918              
919             =head3 Class validation for individual fields
920              
921             You can define a method in your class to perform validation on a field.
922             This method is the equivalent of the field class validate method except it is
923             in the validator/form class, so you might use this
924             validation method if you don't want to create a field subclass.
925              
926             It has access to the form ($self) and the field.
927             This method is called after the field class 'validate' method, and is not
928             called if the value for the field is empty ('', undef). (If you want an
929             error message when the field is empty, use the 'required' flag and message
930             or the form 'validate' method.)
931             The name of this method can be set with 'set_validate' on the field. The
932             default is 'validate_' plus the field name:
933              
934             sub validate_testfield { my ( $self, $field ) = @_; ... }
935              
936             If the field name has dots they should be replaced with underscores.
937              
938             Note that you can also provide a coderef which will be a method on the field:
939              
940             has_field 'foo' => ( methods => { validate => \&validate_foo } );
941              
942             =head3 validate
943              
944             This is a form method that is useful for cross checking values after they have
945             been saved as their final validated value, and for performing more complex
946             dependency validation. It is called after all other field validation is done,
947             and whether or not validation has succeeded, so it has access to the
948             post-validation values of all the fields.
949              
950             This is the best place to do validation checks that depend on the values of
951             more than one field.
952              
953             =head2 Accessing errors
954              
955             Also see L<Data::MuForm::Manual::Errors>.
956              
957             Set an error in a field with C<< $field->add_error('some error string'); >>.
958             Set a form error not tied to a specific field with
959             C<< $self->add_form_error('another error string'); >>.
960             The 'add_error' and 'add_form_error' methods call localization. If you
961             want to skip localization for a particular error, you can use 'push_error'
962             or 'push_form_errors' instead.
963              
964             has_errors - returns true or false
965             error_fields - returns list of fields with errors
966             errors - returns array of error messages for the entire form
967             num_errors - number of errors in form
968              
969             Each field has an array of error messages. (errors, has_errors, num_errors,
970             clear_errors)
971              
972             $form->field('title')->errors;
973              
974             Compound fields also have an array of error_fields.
975              
976             =head2 Clear form state
977              
978             The clear method is called at the beginning of 'process' if the form
979             object is reused, such as when it is persistent,
980             or in tests. If you add other attributes to your form that are set on
981             each request, you may need to either clear those yourself or ensure that
982             they are always set on each process call.
983              
984             =head2 Miscellaneous attributes
985              
986             =head3 name
987              
988             The form's name. Useful for multiple forms. Used for the form element 'id'.
989             When 'field_prefix' is set it is used to construct the field 'id'
990             and 'name'. The default is derived from the form class name.
991              
992             =head3 init_values
993              
994             An 'init_values' object or hashref may be used instead of the 'model' to pre-populate the values
995             in the form. This can be useful when populating a form from default values
996             stored in a similar but different object than the one the form is creating.
997             It can be set in a variety of ways:
998              
999             my $form = MyApp::Form->new( init_values => { .... } );
1000             $form->process( init_values => {...}, ... );
1001             has '+init_values' => ( default => sub { { .... } } );
1002             sub init_values { my $self = shift; .... }
1003              
1004             The method version is useful if the organization of data in your form does
1005             not map to an existing or database object in an automatic way, and you need
1006             to create a different type of object for initialization. (You might also
1007             want to do 'update_model' yourself.)
1008              
1009             You can use both a 'model' and an 'init_values' hashref
1010             when some of the fields in your form come from the database and some
1011             are process or environment type flags that are not in the database.
1012              
1013             =head3 ctx
1014              
1015             Place to store application context for your use in your form's methods.
1016              
1017             =head2 Localizer
1018              
1019             The form has a 'localizer' object which is shared with form fields.
1020             Uses gettext style .po files with names parameters, and is implemented
1021             with internal code borrowed from L<Locale::TextDomain::OO>.
1022              
1023             =head2 Flags
1024              
1025             =head3 validated, is_valid
1026              
1027             Flag that indicates if form has been validated. You might want to use
1028             this flag if you're doing something in between process and returning,
1029             such as setting a stash key. ('is_valid' is a synonym for this flag)
1030              
1031             $form->process( ... );
1032             $c->stash->{...} = ...;
1033             return unless $form->validated;
1034              
1035             =head3 ran_validation
1036              
1037             Flag to indicate that validation has been run. This flag will be
1038             false when the form is initially loaded and displayed, since
1039             validation is not run until MuForm has params to validate.
1040              
1041             =head3 field_prefix
1042              
1043             String to be used as a prefix for field ids and names
1044             in an HTML form. Useful for multiple forms
1045             on the same HTML page. The prefix is stripped off of the fields
1046             before creating the internal field name, and added back in when
1047             returning a parameter hash from the 'fif' method. For example,
1048             the field name in the HTML form could be "book.borrower", and
1049             the field name in the MuForm form (and the database column)
1050             would be just "borrower".
1051              
1052             has '+name' => ( default => 'book' );
1053             has '+field_prefix' => ( default => 'book' );
1054              
1055             Also see the Field attribute "prefixed_name", a convenience function which
1056             will return the field_prefix + "." + field full_name
1057              
1058             =head2 setup
1059              
1060             This is where args passed to 'process' are set, and the form is
1061             filled by params, object, or fields.
1062              
1063             =head1 AUTHOR
1064              
1065             Gerda Shank
1066              
1067             =head1 COPYRIGHT AND LICENSE
1068              
1069             This software is copyright (c) 2017 by Gerda Shank.
1070              
1071             This is free software; you can redistribute it and/or modify it under
1072             the same terms as the Perl 5 programming language system itself.
1073              
1074             =cut