Group
Extension

App-Manoc/lib/App/Manoc/ControllerRole/JQDatatable.pm

package App::Manoc::ControllerRole::JQDatatable;
#ABSTRACT: Support for jQuery DataTable

use Moose::Role;

our $VERSION = '2.99.4'; ##TRIAL VERSION

use MooseX::MethodAttributes::Role;
use namespace::autoclean;


has datatable_search_columns => (
    is      => 'rw',
    isa     => 'ArrayRef[Str]',
    lazy    => 1,
    builder => '_build_datatable_search_columns'
);

has datatable_columns => (
    is  => 'rw',
    isa => 'ArrayRef[Str]',
);

# used add options if needed (JOIN, PREFETCH, ...)
has datatable_search_options => (
    is      => 'rw',
    isa     => 'HashRef',
    default => sub { {} },
);

has datatable_search_callback => ( is => 'rw', );

has datatable_row_callback => ( is => 'rw', );

sub _build_datatable_search_columns {
    my $self = shift;
    $self->datatable_columns or return [];
    return [ @{ $self->datatable_columns } ];
}


sub get_datatable_resultset {
    my ( $self, $c ) = @_;

    return $c->stash->{'resultset'};
}


sub datatable_source : Chained('base') : PathPart('datatable_source') : Args(0) {
    my ( $self, $c ) = @_;

    my $start  = $c->request->param('start') || 0;
    my $length = $c->request->param('length');
    my $draw   = $c->request->param('draw') || 0;
    my $search = $c->request->param("search[value]");

    my $rs = $c->stash->{'datatable_resultset'} ||
        $self->get_datatable_resultset($c);

    my $col_names = $c->stash->{'datatable_columns'} ||
        $self->datatable_columns;

    my $search_columns = $c->stash->{'datatable_search_columns'} ||
        $self->datatable_search_columns;

    my $search_callback = $c->stash->{'datatable_search_callback'} ||
        $self->datatable_search_callback;

    my $row_callback = $c->stash->{'datatable_row_callback'} ||
        $self->datatable_row_callback;

    my $total_rows = $rs->count();

    # create  search filter (WHERE clause)
    my $search_filter = {};
    my $search_attrs  = { %{ $self->datatable_search_options } };

    if ($search) {
        $search_filter = [];

        foreach my $col (@$search_columns) {
            push @$search_filter, { $col => { -like => "%$search%" } };
            $c->log->debug("$col like $search");
        }
    }
    if ($search_callback) {
        ( $search_filter, $search_attrs ) =
            $self->$search_callback( $c, $search_filter, $search_attrs );
    }
    my $filtered_rows = $rs->search_rs( $search_filter, $search_attrs )->count();

    # paging (LIMIT clause)
    if ($length) {
        my $page = $length > 0 ? ( $start + 1 ) / $length : 1;
        $page == int($page) or $page = int($page) + 1;

        $search_attrs->{page} = $page;
        $search_attrs->{rows} = $length;
        $c->log->debug("page = $page length = $length");
    }

    # sorting
    my $sort_column_i = $c->request->param('order[0][column]');
    if ( defined($sort_column_i) ) {
        my $column = $col_names->[$sort_column_i];
        my $dir = $c->request->param("order[0][dir]") eq 'desc' ? '-desc' : '-asc';

        $search_attrs->{order_by} = { $dir => $column };
        $c->log->debug("order by $column $dir");
    }

    #  execute the search and populate results
    my $search_rs = $rs->search_rs( $search_filter, $search_attrs );
    my @rows;
    while ( my $item = $search_rs->next ) {
        my $row;
        if ($row_callback) {
            $row = $self->$row_callback( $c, $item );
        }
        else {
            $row = {};

            foreach my $name (@$col_names) {
                # default accessor is preferred
                my $v = $item->can($name) ? $item->$name : $item->get_column($name);
                $row->{$name} = $v;
            }
        }
        push @rows, $row;
    }

    my $data = {
        draw            => int($draw),
        data            => \@rows,
        recordsTotal    => $total_rows,
        recordsFiltered => $filtered_rows,
    };

    $c->stash( 'json_data' => $data );
    $c->forward('View::JSON');
}

1;
# Local Variables:
# mode: cperl
# indent-tabs-mode: nil
# cperl-indent-level: 4
# cperl-indent-parens-as-block: t
# End:

__END__

=pod

=head1 NAME

App::Manoc::ControllerRole::JQDatatable - Support for jQuery DataTable

=head1 VERSION

version 2.99.4

=head1 DESCRIPTION

Catalyst controller role for helping managing ajax request for datatables.
See L<http://datatables.net/examples/data_sources/server_side.html>

=head1 ACTIONS

=head2 datatable_source

View for datatable AJAX data source

=head1 METHODS

=head2 get_datatable_resultset

Return the resultset to use for datatables.
Defaults to stash->{resultset}

=head1 AUTHORS

=over 4

=item *

Gabriele Mambrini <gmambro@cpan.org>

=item *

Enrico Liguori

=back

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by Gabriele Mambrini.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.