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