1 package Reaction::UI::WidgetClass;
3 use Reaction::ClassExporter;
5 use Reaction::UI::Widget;
9 use aliased 'Reaction::UI::WidgetClass::_OVER';
13 use namespace::clean -except => [ qw(meta) ];
16 # for local() for fragment wrap
17 our ($next_call, $fragment_args, $current_widget, $do_render, $new_args);
19 after 'do_import' => sub {
20 my ($self, $package) = @_;
21 Devel::Declare->install_declarator(
22 $package, 'fragment', DECLARE_NAME,
25 WidgetClass->handle_fragment(@_);
30 after 'setup_and_cleanup' => sub {
31 my ($self, $package) = @_;
34 delete ${"${package}::"}{'fragment'};
36 #Devel::Declare->teardown_for($package);
38 override exports_for_package => sub {
39 my ($self, $package) = @_;
42 my ($collection) = @_;
43 confess "too many args, should be: over \$collection" if @_ > 1;
44 _OVER->new(collection => $collection);
47 my ($name, $over) = @_;
49 my $sig = "should be: render 'name' or render 'name' => over \$coll";
50 if (!defined $name) { confess "name undefined: $sig"; }
51 if (ref $name) { confess "name is a ${\ref $name} ref, not a plain string: $sig"; }
52 if (defined $over && !(blessed($over) && $over->isa(_OVER))) {
53 confess "invalid args after name, $sig";
55 $do_render->($package, $current_widget, $name, $over);
58 my ($name, $value) = @_;
60 my $sig = "should be: arg 'name' => \$value";
64 confess "Not enough arguments, $sig, got: $name => $value";
66 if (!defined $name) { confess "name undefined, $sig"; }
67 if (ref $name) { confess "name is not a string, $sig"; }
69 $new_args->{$name} = $value;
73 return $_{self}->view->localize($value);
76 confess "args passed, should be just call_next; or call_next();"
78 $next_call->(@$fragment_args);
82 $_{viewport}->event_id_for($name);
86 my $vp = $_{viewport};
87 my %args = map{ $vp->event_id_for($_) => $events->{$_} } keys %$events;
88 $vp->ctx->req->uri_with(\%args);
92 return join(' ', map {
93 my $text = HTML::Entities::encode_entities( $attrs->{$_} );
98 my ($name, $sub) = @_;
99 $package->meta->add_method($name, $sub);
103 override default_base => sub { ('Reaction::UI::Widget') };
104 sub handle_fragment {
105 my ($self, $name, $proto, $code) = @_;
106 #warn ($self, $name, $code);
107 return ("_fragment_${name}" => $self->wrap_as_fragment($code));
109 sub wrap_as_fragment {
110 my ($self, $code) = @_;
113 if (ref $_[0] eq 'CODE') { # inside 'around' modifier
116 local $fragment_args = \@_;
118 # $self->$method($do_render, \%_, $new_args)
119 local $current_widget = $_[0];
120 local $do_render = $_[1];
121 local *_ = \%{$_[2]};
122 local $_ = $_[2]->{_};
123 local $new_args = $_[3];
128 __PACKAGE__->meta->make_immutable;
135 Reaction::UI::WidgetClass - Create a new widget class
139 Turns the importing package into a widget class. It will export:
143 =item All of L<Moose>
145 =item All of L<Reaction::Class>
147 =item L<strict> and L<warnings>
149 =item See L</EXPORTS> for this package's own exports
153 It will also set the value of C<default_base> as new superclass. The default is
154 C<Reaction::UI::Widget>.
162 Used in combination with L</render> to render a fragment for a series of values:
164 render fragment_name => over [1, 2, 3];
168 render $fragment_name;
169 render $fragment_name, $over;
171 With only the fragment name as argument, it renders that fragment. If an C<$over>
172 collection is specified with the L</over> keyword, the fragment is rendered once
173 for every value in the collection. The value will be accessible in the topic
178 arg $arg_name, $arg_value;
180 Sets the fragment argument C<$arg_name> to C<$arg_value>;
186 Calls the view's C<localize> method to localize the passed value.
192 Calls the parent fragment.
196 event_id $event_name;
198 Fetches the event id for the event C<$event_name> from the viewport via its C<event_id_for>
205 Returns an L<URI> object with the event ids corresponding to the keys in the C<%events>
206 argument and the values being the values of the hash reference.
212 Builds a string of rendered element attributes out of the C<%attrs> hash reference argument.
216 implements fragment foo { ... };
217 implements bar => sub { ... };
219 Implements a method or a fragment in the widget class.
223 fragment foo { ... };
225 Creates a new fragment named C<foo> with a implementation in the block.
229 See L<Reaction::Class> for authors.
233 See L<Reaction::Class> for the license.