| CatalystX-CRUD-YUI documentation | Contained in the CatalystX-CRUD-YUI distribution. |
CatalystX::CRUD::YUI::LiveGrid - ExtJS LiveGrid objects
my $livegrid = $yui->livegrid(
results => $results, # CX::CRUD::Results or CX::CRUD::Object
controller => $controller,
form => $form,
method_name => $rel_info->{method},
col_names => $form->metadata->field_methods,
c => $c, # Catalyst context object
);
$livegrid->serialize; # returns serialized results
$livegrid->count; # returns number of rows
This class represents the data necessary to support the ExtJS-base LiveGrid component http://www.siteartwork.de/livegrid/.
Create a YUI LiveGrid object. You usually call this via CatalystX::CRUD::YUI->livegrid( opts ).
opts should include:
The results object passed in. May be either a CatalystX::CRUD::Results instance or CatalystX::CRUD::Object instance.
If a Results instance, each object in the Results set will be serialized.
If a Object instance, each object returned by method_name will be serialized.
The form object should be an instance of the Form class that corresponds to the data being serialized. In the case where results isa CatalystX::CRUD::Results object, form should be a Form corresponding to the object class in CatalystX::CRUD::Results->results(). In the case where results isa CatalystX::CRUD::Object, form should be a Form corresponding to the foreign object class represented by method_name.
The controller object should be the governing controller for the objects being serialized, i.e., the controller governing form.
The new LiveGrid has the following accessors available:
The primary key of the table that results represents.
An arrayref of column hashrefs. YUI LiveGrid API requires these.
The url for fetching JSON results.
A hashref of foreign key information.
An arrayref of column names. Used for filtering table by specific column values.
An arrayref of column names. Defaults to form->metadata->field_methods.
An arrayref of hashrefs. These are serialized from results.
The number of items in data.
User-level accessor. You can get/set this to whatever you want.
NOTE: If you pass a CatalystX::CRUD::Object instance as results to new(), the object must implement a primary_key_uri_escaped() method that conforms to the syntax defined by CatalystX::CRUD::Controller make_primary_key_string(). See Rose::DBx::Object::MoreHelpers for one example.
Return the column hashref meta for field_name. The hashref has 3 keys: key, label, and sortable.
Returns LiveGrid as array ref of hash refs, suitable for conversion to JSON or other transport type.
Returns hash ref suitable for JSON-ifying and passing to the LiveGrid JsonReader constructor.
Returns array ref suitable for JSON-ifying and passing to the LiveGrid JsonReader constructor.
Returns array ref suitable for JSON-ifying for LiveGrid JS.
Peter Karman, <karman@cpan.org>
Please report any bugs or feature requests to
bug-catalystx-crud-yui@rt.cpan.org, or through the web interface at
http://rt.cpan.org. I will be notified, and then you'll automatically be
notified of progress on your bug as I make changes.
The Minnesota Supercomputing Institute http://www.msi.umn.edu/
and NALD http://www.nald.ca/
sponsored the development of this software.
Copyright 2008 by the Regents of the University of Minnesota.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| CatalystX-CRUD-YUI documentation | Contained in the CatalystX-CRUD-YUI distribution. |
package CatalystX::CRUD::YUI::LiveGrid; use warnings; use strict; use Carp; use Data::Dump qw( dump ); use MRO::Compat; use mro "c3"; use base qw( Class::Accessor::Fast ); use JSON::XS (); use Scalar::Util qw( blessed ); use CatalystX::CRUD::YUI::Serializer; our $VERSION = '0.025'; __PACKAGE__->mk_accessors( qw( yui results controller form c method_name pk columns show_related_values col_filter text_columns col_names url count counter sort_by show_remove_button serializer_class serializer hide_pk_columns sort_dir title excel_url ) );
sub new { my $self = shift->next::method( ref $_[0] ? @_ : {@_} ); $self->{serializer_class} ||= 'CatalystX::CRUD::YUI::Serializer'; $self->_init; return $self; } sub _init { my $self = shift; my $results = $self->{results} or croak "results required"; my $controller = $self->{controller} or croak "controller required"; my $form = $self->{form} or croak "form required"; my $app = ($self->{c} || $form->app) or croak "\$c object required"; $self->{hide_pk_columns} = $controller->hide_pk_columns; # may be undef. this is the method we call on the the parent object, # where parent $results isa RDBO and we are creating a livegrid out # of its related objects. my $method_name = $self->{method_name}; my @col_names = @{ $self->{col_names} || $form->metadata->field_methods }; $self->pk( ref $controller->primary_key ? $controller->primary_key : [ $controller->primary_key ] ); $self->columns( [] ); $self->show_related_values( {} ); $self->col_filter( [] ); #carp "col_names for $results: " . dump $self->col_names; #carp dump $results; #Carp::cluck(); if ( $results->isa('CatalystX::CRUD::Results') && defined $results->query ) { $self->url( $app->uri_for( $controller->action_for('livegrid'), $results->query->{plain_query} || {} ) ); $self->sort_by( $form->metadata->default_sort_by || $self->pk->[0] ); } else { #carp "results isa " . $results->delegate; #carp "controller isa " . $controller; if ( !$method_name ) { croak "method_name required for CatalystX::CRUD::Object livegrid"; } $self->url( $app->uri_for( $controller->action_for( $results->primary_key_uri_escaped, 'livegrid_related', $method_name, ) ) ); $self->sort_by( $form->metadata->default_related_sort_by || $self->pk->[0] ); } $self->{url} .= '?' unless $self->{url} =~ m/\?/; my @filtered_col_names; for my $field_name (@col_names) { # we include PKs specially at the end. # exclude them here if they are single-col # (since those are often autoincrem) # but we turn on the 'hide' flag so that even # though they are rendered, they are invisible to user if ( @{ $self->{pk} } == 1 and $self->{pk}->[0] eq $field_name ) { $self->{hide_pk_columns} = 1 unless defined $self->{hide_pk_columns}; next; } push( @filtered_col_names, $field_name ); my $isa_field = $form->field($field_name); my $isa_chain = $field_name =~ m/\./; my $col_def = { key => $field_name, # must force label object to stringify label => defined($isa_field) ? $isa_field->label . '' : ( $form->metadata->labels->{$field_name} || $field_name ), sortable => ( $isa_field || $isa_chain ) ? JSON::XS::true() : JSON::XS::false(), sort_prefix => ( $form->metadata->sort_prefix->{$field_name} || '' ), type => $isa_field ? $self->_get_col_type( $isa_field->class ) : 'string', # per-column click url => $app->uri_for( $form->metadata->field_uri($field_name) ), }; push( @{ $self->{columns} }, $col_def ); push( @{ $self->{col_filter} }, { dataIndex => $col_def->{key}, type => $col_def->{type} } ); if ( ( $isa_field and $col_def->{type} eq 'string' ) or $isa_chain ) { push( @{ $self->{text_columns} }, $field_name ); } next unless $form->metadata->show_related_values; next unless $form->metadata->is_related_field($field_name); my $rel_info = $form->metadata->related_field($field_name); my $ffield = $form->metadata->show_related_field_using( $rel_info->{foreign_class}, $field_name, ); $self->{show_related_values}->{$field_name} = { method => $rel_info->{method}, foreign_field => $ffield, }; next; # TODO allow for non-local column names to be filtered on if ( $isa_field and $col_def->{type} ne 'string' ) { push( @{ $self->{text_columns} }, $rel_info->{method} ); } } # always include pk since that's what is used for links my $pk_name = join( ';;', @{ $self->{pk} } ); my $col_def = { key => $pk_name, # must force label object to stringify label => ( $form->metadata->labels->{$pk_name} || join( ' ', map { ucfirst($_) } split( m/\_/, $pk_name ) ) ), sortable => $pk_name =~ m/;;/ ? JSON::XS::false() : JSON::XS::true(), type => 'pk', # per-column click url => $app->uri_for( $form->metadata->field_uri($pk_name) ), }; push( @{ $self->{columns} }, $col_def ); push( @{ $self->{col_filter} }, { dataIndex => $col_def->{key}, type => $col_def->{type} } ); push( @filtered_col_names, $self->pk ); $self->col_names( \@filtered_col_names ); if ( $self->{sort_by} =~ s/ (ASC|DESC)$//i ) { $self->{sort_dir} = $1; } else { $self->{sort_dir} = 'ASC'; } my $moniker; my $object_class = $form->metadata->object_class; if ( $object_class->can('moniker') ) { $moniker = $object_class->moniker; } else { $moniker = $object_class; } $moniker =~ s/^.+:://; $self->{title} = 'Results for ' . $moniker; return $self; }
sub column { my $self = shift; my $field_name = shift; for my $col ( @{ $self->columns } ) { return $col if $col->{key} eq $field_name; } return undef; }
sub serialize { my $self = shift; my $serializer = $self->serializer || $self->serializer_class->new; return $serializer->serialize_livegrid($self); } sub _get_col_type { my ( $self, $class ) = @_; #warn "class = $class\n"; $class ||= 'text'; if ( $class =~ m/text|char|autocomplete/ ) { return 'string'; } elsif ( $class =~ m/int|num|radio|serial/ ) { return 'numeric'; } elsif ( $class eq 'boolean' ) { return 'boolean'; } elsif ( $class =~ m/date|time/ ) { return 'date'; } else { return 'string'; } }
sub json_reader_opts { my $self = shift; return { root => 'response.value.items', versionProperty => 'response.value.version', totalProperty => 'response.value.total_count', id => join( ';;', @{ $self->pk } ), } }
sub json_reader_columns { my $self = shift; my $cols = $self->{columns}; my @new; for my $col (@$cols) { my $hash = { name => $col->{key} }; if ( $col->{sortable} ) { $hash->{sortType} = ( $col->{type} eq 'string' ) ? 'string' : 'int'; } push( @new, $hash ); } return \@new; }
sub column_defs { my $self = shift; my @defs; for my $col ( @{ $self->columns } ) { my $def = { header => $col->{label}, align => 'left', sortable => $col->{sortable}, sortPrefix => $col->{sort_prefix}, dataIndex => $col->{key}, type => $col->{type}, }; if ( $def->{type} eq 'pk' && $self->{hide_pk_columns} ) { $def->{hidden} = JSON::XS::true(); $def->{type} = 'string'; } if ( $col->{key} =~ m/\./ ) { $def->{type} = 'string'; } push( @defs, $def ); } return \@defs; } 1; __END__