Permalink
Browse files

more work on repeatable js

  • Loading branch information...
1 parent bf7de5c commit 3ee7a54bc87db4d40e4cc0de24d0eb07684eb933 @gshank committed Feb 7, 2013
@@ -1059,6 +1059,17 @@ sub get_tag {
if ( $self->form && $self->form->block_exists($block_name) );
return '';
}
+has 'for_js' => (
+ isa => 'HashRef',
+ traits => ['Hash'],
+ is => 'rw',
+ default => sub { {} },
+ handles => {
+ set_for_js => 'set',
+ has_for_js => 'count',
+ clear_for_js => 'clear',
+ }
+);
has 'action' => ( is => 'rw' );
has 'posted' => ( is => 'rw', isa => 'Bool', clearer => 'clear_posted', predicate => 'has_posted' );
@@ -1256,6 +1267,7 @@ sub clear {
$self->clear_use_init_obj_over_item;
$self->clear_no_update;
$self->clear_info_message;
+ $self->clear_for_js;
}
sub values { shift->value }
@@ -346,10 +346,13 @@ sub _merge_updates {
$field_attr->{widget_wrapper} = $widget_wrapper;
}
# add widget and wrapper roles to field traits
- if( $widget ) {
+ if ( $widget ) {
my $widget_role = $self->get_widget_role( $widget, 'Field' );
+ push @{$field_attr->{traits}}, $widget_role;
+ }
+ if ( $widget_wrapper ) {
my $wrapper_role = $self->get_widget_role( $widget_wrapper, 'Wrapper' );
- push @{$field_attr->{traits}}, $widget_role, $wrapper_role;
+ push @{$field_attr->{traits}}, $wrapper_role;
}
}
return $field_attr;
@@ -0,0 +1,61 @@
+package HTML::FormHandler::Field::AddElement;
+use HTML::FormHandler::Moose;
+extends 'HTML::FormHandler::Field::Display';
+use HTML::FormHandler::Render::Util ('process_attrs');
+
+=head1 NAME
+
+HTML::FormHandler::Field::AddElement
+
+=head1 SYNOPSIS
+
+EXAMPLE field for rendering an AddElement field for
+doing javascript additions of repeatable elements.
+
+You probably want to make your own.
+
+The main requirements are that the button have 1) the
+'add_element' class, 2) a 'data-rep-id' attribute that
+contains the id of the repeatable to which you want to
+add an element.
+
+=head1 ATTRIBUTES
+
+ has_field 'add_element' => ( type => 'AddElement', repeatable => 'foo',
+ value => 'Add another foo',
+ );
+
+=head2 repeatable
+
+Requires the name of a Repeatable sibling field.
+
+=head2 value
+
+The value of the button that's rendered, 'Add Element' by default.
+
+=cut
+
+has 'repeatable' => ( is => 'rw', isa => 'Str', required => 1 );
+has '+do_wrapper' => ( default => 1 );
+has '+value' => ( default => 'Add Element' );
+
+sub build_render_method {
+ return sub {
+ my ( $self, $result ) = @_;
+ $result ||= $self->result;
+
+ my $rep_field = $self->parent->field($self->repeatable);
+ die "Invalid repeatable name in field " . $self->name unless $rep_field;
+ my $value = $self->html_filter($self->_localize($self->value));
+ my $attrs = $self->element_attributes($result);
+ push @{$attrs->{class}}, ( 'add_element', 'btn' );
+ $attrs->{'data-rep-id'} = $rep_field->id;
+ $attrs->{id} = $self->id;
+ my $attr_str = process_attrs($attrs);
+ my $output = qq{<div$attr_str>$value</div>};
+ $output = $self->wrap_field($self->result, $output);
+ return $output;
+ };
+}
+
+1;
@@ -41,51 +41,43 @@ or set the name of the rendering method:
....
}
-You can also supply an 'html' method with a trait or a custom field. See examples
-in t/field_traits.t and t/xt/display.t of the distribution.
+or provide a 'render_method':
+
+ has_field 'my_button' => ( type => 'Display', render_method => \&render_my_button );
+ sub render_my_button {
+ my $self = shift;
+ ....
+ return '...';
+ }
=cut
has 'html' => ( is => 'rw', isa => 'Str', builder => 'build_html', lazy => 1 );
sub build_html {''}
has 'set_html' => ( isa => 'Str', is => 'ro');
-sub _set_html_meth {
- my $self = shift;
- return $self->set_html if $self->set_html;
- my $name = $self->full_name;
- $name =~ s/\./_/g;
- $name =~ s/_\d+_/_/g;
- return 'html_' . $name;
-}
-sub _can_form_html {
- my $self = shift;
- my $set_html = $self->_set_html_meth;
- return
- unless $self->form &&
- $set_html &&
- $self->form->can( $set_html );
- return $set_html;
-}
-sub _form_html {
+has '+do_label' => ( default => 0 );
+
+has 'render_method' => (
+ traits => ['Code'],
+ is => 'ro',
+ isa => 'CodeRef',
+ lazy => 1,
+ predicate => 'does_render_method',
+ handles => { 'render' => 'execute_method' },
+ builder => 'build_render_method',
+);
+
+sub build_render_method {
my $self = shift;
- return unless (my $meth = $self->_can_form_html);
- if( $self->form->meta->has_attribute( $meth ) ) {
- return $self->form->$meth;
- }
- else {
- return $self->form->$meth($self);
- }
-}
-sub render {
- my $self = shift;
- if ( my $meth = $self->_can_form_html ) {
- return $self->form->$meth( $self );
- }
- elsif ( $self->html ) {
+ my $set_html = $self->set_html;
+ $set_html ||= "html_" . HTML::FormHandler::Field::convert_full_name($self->full_name);
+ return sub { my $self = shift; $self->form->$set_html($self); }
+ if ( $self->form && $self->form->can($set_html) );
+ return sub {
+ my $self = shift;
return $self->html;
- }
- return '';
+ };
}
sub _result_from_object {
@@ -96,11 +88,6 @@ sub _result_from_object {
return $result;
}
-after 'clear_data' => sub {
- my $self = shift;
- $self->clear_value;
-};
-
__PACKAGE__->meta->make_immutable;
use namespace::autoclean;
1;
@@ -1,35 +0,0 @@
-package HTML::FormHandler::Field::Render;
-# ABSTRACT: display only field
-
-use Moose;
-extends 'HTML::FormHandler::Field::NoValue';
-use namespace::autoclean;
-
-=head1 SYNOPSIS
-
-This is an alternative to the Display field. It allows
-you to provide a 'render_method', instead of using
-the Display field's method of providing html.
-
-=cut
-
-has 'render_method' => (
- traits => ['Code'],
- is => 'ro',
- isa => 'CodeRef',
- predicate => 'does_render_method',
- handles => { 'render' => 'execute_method' },
- default => sub { \&default_render },
-);
-
-sub default_render {
- my $self = shift;
- return $self->html;
-}
-
-has 'html' => ( is => 'rw', isa => 'Str', default => '' );
-
-
-__PACKAGE__->meta->make_immutable;
-use namespace::autoclean;
-1;
@@ -139,7 +139,7 @@ has 'init_contains' => ( is => 'rw', isa => 'HashRef', traits => ['Hash'],
has 'num_when_empty' => ( isa => 'Int', is => 'rw', default => 1 );
has 'num_extra' => ( isa => 'Int', is => 'rw', default => 0 );
-has 'extra_for_js' => ( isa => 'Str', is => 'rw' );
+has 'setup_for_js' => ( isa => 'Bool', is => 'rw' );
has 'index' => ( isa => 'Int', is => 'rw', default => 0 );
has 'auto_id' => ( isa => 'Bool', is => 'rw', default => 0 );
has 'is_repeatable' => ( is => 'ro', default => 1 );
@@ -279,29 +279,28 @@ sub _result_from_input {
$index++;
}
}
- $self->_add_extra_for_js if $self->extra_for_js;
$self->index($index);
+ $self->_setup_for_js if $self->setup_for_js;
$self->result->_set_field_def($self);
return $self->result;
}
-sub _extra_for_js_id {
+sub _setup_for_js {
my $self = shift;
- return '' unless $self->extra_for_js;
- return $self->full_name . "." . $self->extra_for_js . ".wrp";
-}
-sub _add_extra_for_js {
- my $self = shift;
- $self->_add_extra($self->extra_for_js);
- my $field = $self->field($self->extra_for_js);
-
- # add an extra div around the field so that the html can be easily pulled out
- # need to clone tags, otherwise tags shared with all repeatable instances
- my $tags = data_clone( $field->tags );
- my $id = $self->_extra_for_js_id;
- $tags->{before_wrapper} = qq{<div class="for_js" id="$id">};
- $tags->{after_wrapper} = '</div>';
- $field->tags($tags);
+ return unless $self->form;
+ my $full_name = $self->full_name;
+ my $index_level =()= $full_name =~ /{index\d+}/g;
+ $index_level++;
+ my $field_name = "{index-$index_level}";
+ my $field = $self->_add_extra($field_name);
+ my $rendered = $field->render;
+ # remove extra result & field, now that it's rendered
+ $self->result->_pop_result;
+ $self->_pop_field;
+ # set the information in the form
+ # $self->index is the index of the next instance
+ $self->form->set_for_js( $self->full_name,
+ { index => $self->index, html => $rendered, level => $index_level } );
}
# this is called when there is an init_object or a db item with values
@@ -339,8 +338,8 @@ sub _result_from_object {
$index++;
}
}
- $self->_add_extra_for_js if $self->extra_for_js;
$self->index($index);
+ $self->_setup_for_js if $self->setup_for_js;
$values = \@new_values if scalar @new_values;
$self->_set_value($values);
$self->result->_set_field_def($self);
@@ -356,6 +355,7 @@ sub _add_extra {
$result = $field->_result_from_fields($result);
$self->result->add_result($result) if $result;
$self->add_field($field);
+ return $field;
}
sub add_extra {
@@ -394,8 +394,8 @@ sub _result_from_fields {
$index++;
$count--;
}
- $self->_add_extra_for_js if $self->extra_for_js;
$self->index($index);
+ $self->_setup_for_js if $self->setup_for_js;
$self->result->_set_field_def($self);
return $result;
}
@@ -57,6 +57,7 @@ has 'fields' => (
num_fields => 'count',
has_fields => 'count',
set_field_at => 'set',
+ _pop_field => 'pop',
}
);
# This is for updates applied via roles or compound field classes; allows doing
Oops, something went wrong.

0 comments on commit 3ee7a54

Please sign in to comment.