File Coverage

blib/lib/HTML/FormHandler/Render/Simple.pm
Criterion Covered Total %
statement 146 178 82.0
branch 43 56 76.7
condition 19 24 79.1
subroutine 16 20 80.0
pod 11 17 64.7
total 235 295 79.6


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Render::Simple;
2             # ABSTRACT: simple rendering role
3             $HTML::FormHandler::Render::Simple::VERSION = '0.40068';
4 8     8   14602 use Moose::Role;
  8         23  
  8         73  
5              
6             requires( 'sorted_fields', 'field' );
7              
8 8     8   43657 use HTML::FormHandler::Render::Util ('process_attrs', 'ucc_widget');
  8         26  
  8         65  
9              
10              
11              
12             sub render {
13 6     6 1 2183 my $self = shift;
14 6         67 my $output = $self->render_start;
15              
16 6         43 $output .= $self->render_form_errors;
17              
18 6         51 foreach my $field ( $self->sorted_fields ) {
19 39         215 $output .= $self->render_field($field);
20             }
21              
22 6         104 $output .= $self->render_end;
23 6         101 return $output;
24             }
25              
26              
27             sub render_form_errors {
28 6     6 0 20 my $self = shift;
29              
30 6 100       83 return '' unless $self->has_form_errors;
31 1         3 my $output = "\n<div class=\"form_errors\">";
32             $output .= qq{\n<span class="error_message">$_</span>}
33 1         8 for $self->all_form_errors;
34 1         2 $output .= "\n</div>";
35 1         4 return $output;
36             }
37              
38             sub render_field {
39 96     96 1 752 my ( $self, $field ) = @_;
40              
41 96 100       416 if ( ref( \$field ) eq 'SCALAR' ) {
42 2         15 $field = $self->field($field);
43             }
44 96 50 33     1001 die "must pass field to render_field"
45             unless ( defined $field && $field->isa('HTML::FormHandler::Field') );
46             # widgets should be in camel case, since they are Perl package names
47 96         3649 my $widget = ucc_widget($field->widget);
48 96 100       375 return '' if $widget eq 'no_render';
49 91         183 my $rendered_field;
50 91         375 my $form_render = 'render_' . $widget;
51 91 100       549 if ( $self->can($form_render) ) {
    50          
52 90         379 $rendered_field = $self->$form_render($field);
53             }
54             elsif ( $field->can('render') ) {
55 1         7 $rendered_field = $field->render;
56             }
57             else {
58 0         0 die "No widget method found for '$widget' in H::F::Render::Simple";
59             }
60 91         458 return $self->wrap_field( $field, $rendered_field );
61             }
62              
63             sub wrap_field {
64 67     67 0 241 my ( $self, $field, $rendered_field ) = @_;
65              
66 67 50       432 return "\n$rendered_field" if $field->uwrapper eq 'none';
67 67 50       2275 return "\n$rendered_field" if ! $field->do_wrapper;
68              
69 67         190 my $output = "\n";
70              
71 67         368 my $wrapper_tag = $field->get_tag('wrapper_tag');
72 67 50 66     587 $wrapper_tag ||= $field->has_flag('is_repeatable') ? 'fieldset' : 'div';
73 67         400 my $attrs = process_attrs($field->wrapper_attributes);
74              
75 67         312 $output .= qq{<$wrapper_tag$attrs>};
76 67 100 66     371 if( $wrapper_tag eq 'fieldset' ) {
    100 66        
77 2         11 $output .= '<legend>' . $field->loc_label . '</legend>';
78             }
79             elsif ( ! $field->get_tag('label_none') && $field->do_label && length( $field->label ) > 0 ) {
80 57         300 $output .= "\n" . $self->render_label($field);
81             }
82              
83 67         250 $output .= "\n$rendered_field";
84             $output .= qq{\n<span class="error_message">$_</span>}
85 67         589 for $field->all_errors;
86              
87 67         239 $output .= "\n</$wrapper_tag>";
88              
89 67         445 return "$output";
90             }
91              
92             sub render_text {
93 43     43 1 116 my ( $self, $field ) = @_;
94 43         240 my $output = '<input type="' . $field->input_type . '" name="';
95 43         1294 $output .= $field->html_name . '"';
96 43         1254 $output .= ' id="' . $field->id . '"';
97 43 100       1446 $output .= ' size="' . $field->size . '"' if $field->size;
98 43 100       1293 $output .= ' maxlength="' . $field->maxlength . '"' if $field->maxlength;
99 43         226 $output .= ' value="' . $field->html_filter($field->fif) . '"';
100 43         230 $output .= process_attrs($field->element_attributes);
101 43         153 $output .= ' />';
102 43         133 return $output;
103             }
104              
105             sub render_password {
106 0     0 1 0 my ( $self, $field ) = @_;
107 0         0 my $output = '<input type="password" name="';
108 0         0 $output .= $field->html_name . '"';
109 0         0 $output .= ' id="' . $field->id . '"';
110 0 0       0 $output .= ' size="' . $field->size . '"' if $field->size;
111 0 0       0 $output .= ' maxlength="' . $field->maxlength . '"' if $field->maxlength;
112 0         0 $output .= ' value="' . $field->html_filter($field->fif) . '"';
113 0         0 $output .= process_attrs($field->element_attributes);
114 0         0 $output .= ' />';
115 0         0 return $output;
116             }
117              
118             sub render_hidden {
119 5     5 1 19 my ( $self, $field ) = @_;
120 5         18 my $output = '<input type="hidden" name="';
121 5         340 $output .= $field->html_name . '"';
122 5         175 $output .= ' id="' . $field->id . '"';
123 5         40 $output .= ' value="' . $field->html_filter($field->fif) . '"';
124 5         55 $output .= process_attrs($field->element_attributes);
125 5         21 $output .= ' />';
126 5         22 return $output;
127             }
128              
129             sub render_select {
130 14     14 1 67 my ( $self, $field ) = @_;
131              
132 14         491 my $multiple = $field->multiple;
133 14         430 my $id = $field->id;
134 14         423 my $output = '<select name="' . $field->html_name . '"';
135 14         55 $output .= qq{ id="$id"};
136 14 100       71 $output .= ' multiple="multiple"' if $multiple == 1;
137 14 100       477 $output .= ' size="' . $field->size . '"' if $field->size;
138 14         102 my $html_attributes = process_attrs($field->element_attributes);
139 14         49 $output .= $html_attributes;
140 14         34 $output .= '>';
141 14         41 my $index = 0;
142 14 50       527 if( defined $field->empty_select ) {
143 0         0 $output .= '<option value="">' . $field->_localize($field->empty_select) . '</option>';
144             }
145 14         82 my $fif = $field->fif;
146 14         39 my %fif_lookup;
147 14 100       70 @fif_lookup{@$fif} = () if $multiple;
148 14         32 foreach my $option ( @{ $field->{options} } ) {
  14         55  
149 47         128 my $value = $option->{value};
150 47         1716 $output .= '<option value="'
151             . $field->html_filter($value)
152             . qq{" id="$id.$index"};
153 47 100 100     184 if( defined $option->{disabled} && $option->{disabled} ) {
154 4         11 $output .= ' disabled="disabled"';
155             }
156 47 50       153 if ( defined $fif ) {
157 47 100 100     276 if ( $multiple && exists $fif_lookup{$value} ) {
    100          
158 8         24 $output .= ' selected="selected"';
159             }
160             elsif ( $fif eq $value ) {
161 4         15 $output .= ' selected="selected"';
162             }
163             }
164 47         98 $output .= $html_attributes;
165 47         115 my $label = $option->{label};
166 47 50       1498 $label = $field->_localize($label) if $field->localize_labels;
167 47         1601 $output .= '>' . ( $field->html_filter($label) ) . '</option>';
168 47         169 $index++;
169             }
170 14         38 $output .= '</select>';
171 14         58 return $output;
172             }
173              
174             sub render_checkbox {
175 10     10 1 40 my ( $self, $field ) = @_;
176              
177 10         371 my $output = '<input type="checkbox" name="' . $field->html_name . '"';
178 10         333 $output .= ' id="' . $field->id . '"';
179 10         381 $output .= ' value="' . $field->html_filter($field->checkbox_value) . '"';
180 10 100       79 $output .= ' checked="checked"' if $field->fif eq $field->checkbox_value;
181 10         72 $output .= process_attrs($field->element_attributes);
182 10         38 $output .= ' />';
183 10         36 return $output;
184             }
185              
186             sub render_radio_group {
187 5     5 1 23 my ( $self, $field ) = @_;
188              
189 5         19 my $output = " <br />";
190 5         15 my $index = 0;
191 5         15 foreach my $option ( @{ $field->options } ) {
  5         202  
192 10         321 my $id = $field->id . ".$index";
193 10         408 $output .= qq{<label for="$id"><input type="radio" value="} . $field->html_filter($option->{value}) . '"';
194 10         286 $output .= ' name="' . $field->html_name . '" id="' . "$id\"";
195 10 100       62 $output .= ' checked="checked"' if $option->{value} eq $field->fif;
196 10         30 $output .= ' />';
197 10         377 $output .= $field->html_filter($option->{label}) . '</label><br />';
198 10         36 $index++;
199             }
200 5         22 return $output;
201             }
202              
203             sub render_textarea {
204 5     5 1 18 my ( $self, $field ) = @_;
205 5   100     55 my $fif = $field->fif || '';
206 5         159 my $id = $field->id;
207 5   100     176 my $cols = $field->cols || 10;
208 5   100     174 my $rows = $field->rows || 5;
209 5         193 my $name = $field->html_name;
210              
211 5         50 my $output =
212             qq(<textarea name="$name" id="$id" )
213             . process_attrs($field->element_attributes)
214             . qq(rows="$rows" cols="$cols">)
215             . $field->html_filter($fif)
216             . q(</textarea>);
217              
218 5         29 return $output;
219             }
220              
221             sub render_upload {
222 0     0 0 0 my ( $self, $field ) = @_;
223              
224 0         0 my $output;
225 0         0 $output = '<input type="file" name="';
226 0         0 $output .= $field->html_name . '"';
227 0         0 $output .= ' id="' . $field->id . '"';
228 0         0 $output .= process_attrs($field->element_attributes);
229 0         0 $output .= ' />';
230 0         0 return $output;
231             }
232              
233             sub render_label {
234 81     81 0 255 my ( $self, $field ) = @_;
235              
236 81         472 my $attrs = process_attrs( $field->label_attributes );
237 81         516 my $label = $field->html_filter($field->loc_label);
238 81 100       2948 $label .= $field->get_tag('label_after')
239             if( $field->tag_exists('label_after') );
240 81 50       2753 my $label_tag = $field->tag_exists('label_tag') ? $field->get_tag('label_tag') : 'label';
241 81         2368 return qq{<$label_tag$attrs for="} . $field->id . qq{">$label</$label_tag>};
242             }
243              
244             sub render_compound {
245 3     3 1 10 my ( $self, $field ) = @_;
246              
247 3         6 my $output = '';
248 3         19 foreach my $subfield ( $field->sorted_fields ) {
249 9         40 $output .= $self->render_field($subfield);
250             }
251 3         11 return $output;
252             }
253              
254             sub render_submit {
255 5     5 1 40 my ( $self, $field ) = @_;
256              
257 5         16 my $output = '<input type="submit" name="';
258 5         211 $output .= $field->html_name . '"';
259 5         184 $output .= ' id="' . $field->id . '"';
260 5         49 $output .= process_attrs($field->element_attributes);
261 5         209 $output .= ' value="' . $field->html_filter($field->_localize($field->value)) . '" />';
262 5         22 return $output;
263             }
264              
265             sub render_reset {
266 0     0 0   my ( $self, $field ) = @_;
267              
268 0           my $output = '<input type="reset" name="';
269 0           $output .= $field->html_name . '"';
270 0           $output .= ' id="' . $field->id . '"';
271 0           $output .= process_attrs($field->element_attributes);
272 0           $output .= ' value="' . $field->html_filter($field->value) . '" />';
273 0           return $output;
274             }
275              
276             sub render_captcha {
277 0     0 0   my ( $self, $field ) = @_;
278              
279 0           my $output .= '<img src="' . $self->captcha_image_url . '"/>';
280 0           $output .= '<input id="' . $field->id . '" name="';
281 0           $output .= $field->html_name . '"/>';
282 0           return $output;
283             }
284              
285              
286 8     8   13625 use namespace::autoclean;
  8         29  
  8         87  
287             1;
288              
289             __END__
290              
291             =pod
292              
293             =encoding UTF-8
294              
295             =head1 NAME
296              
297             HTML::FormHandler::Render::Simple - simple rendering role
298              
299             =head1 VERSION
300              
301             version 0.40068
302              
303             =head1 SYNOPSIS
304              
305             This is a Moose role that is an example of a simple rendering
306             routine for L<HTML::FormHandler>. It's here as an example of
307             how to write a custom renderer in one package, if you prefer
308             that to using the widgets. It won't always be updated with
309             improvements by default, because it was becoming a lot of work to update
310             the rendering in multiple places.
311              
312             For a 'MyApp::Form::Renderer' which you've created and modified,
313             in your Form class:
314              
315             package MyApp::Form::Silly;
316             use Moose;
317             extends 'HTML::FormHandler::Model::DBIC';
318             with 'MyApp::Form::Renderers';
319              
320             In a template:
321              
322             [% form.render %]
323              
324             The widgets are rendered with C<< $field->render >>; rendering
325             routines from a class like this use C<< $form->render_field('field_name') >>
326             to render individual fields:
327              
328             [% form.render_field( 'title' ) %]
329              
330             =head1 DESCRIPTION
331              
332             This role provides HTML output routines for the 'widget' types
333             defined in the provided FormHandler fields. Each 'widget' name
334             has a 'widget_$name' method here.
335              
336             These widget routines output strings with HTML suitable for displaying
337             form fields.
338              
339             The widget for a particular field can be defined in the form. You can
340             create additional widget routines in your form for custom widgets.
341              
342             The fill-in-form values ('fif') are cleaned with the 'render_filter'
343             method of the base field class. You can change the filter to suit
344             your own needs: see L<HTML::FormHandler::Manual::Rendering>
345              
346             =head2 render
347              
348             To render all the fields in a form in sorted order (using
349             'sorted_fields' method).
350              
351             =head2 render_start, render_end
352              
353             These use the methods in L<HTML::FormHandler::Widget::Form::Simple> now. If
354             you want to customize them, copy them to your own package.
355              
356             Will render the beginning and ending <form> tags and fieldsets. Allows for easy
357             splitting up of the form if you want to hand-render some of the fields.
358              
359             [% form.render_start %]
360             [% form.render_field('title') %]
361             <insert specially rendered field>
362             [% form.render_field('some_field') %]
363             [% form.render_end %]
364              
365             =head2 render_field
366              
367             Render a field passing in a field object or a field name
368              
369             $form->render_field( $field )
370             $form->render_field( 'title' )
371              
372             =head2 render_text
373              
374             Output an HTML string for a text widget
375              
376             =head2 render_password
377              
378             Output an HTML string for a password widget
379              
380             =head2 render_hidden
381              
382             Output an HTML string for a hidden input widget
383              
384             =head2 render_select
385              
386             Output an HTML string for a 'select' widget, single or multiple
387              
388             =head2 render_checkbox
389              
390             Output an HTML string for a 'checkbox' widget
391              
392             =head2 render_radio_group
393              
394             Output an HTML string for a 'radio_group' selection widget.
395             This widget should be for a field that inherits from 'Select',
396             since it requires the existence of an 'options' array.
397              
398             =head2 render_textarea
399              
400             Output an HTML string for a textarea widget
401              
402             =head2 render_compound
403              
404             Renders field with 'compound' widget
405              
406             =head2 render_submit
407              
408             Renders field with 'submit' widget
409              
410             =head1 AUTHOR
411              
412             FormHandler Contributors - see HTML::FormHandler
413              
414             =head1 COPYRIGHT AND LICENSE
415              
416             This software is copyright (c) 2017 by Gerda Shank.
417              
418             This is free software; you can redistribute it and/or modify it under
419             the same terms as the Perl 5 programming language system itself.
420              
421             =cut