Using Catalyst::Example::InstantCRUD you can have sortable lists out of box.

Sortable List

After creating the scaffolding (see Scaffolding in Movies of Catalyst in Action and/or MoviesScaffoldingDemoTranscript) you have a nice list view where you can view all of your rows in the database. You would like to add the functionality of sorting the data (by clicking on the column headers); this page describes how to do that. This is a server side sorting solution and it should play nice with paging and other parameters to the page - like sorting a search result. Another solution to sorting is JavaScript sorting - this would work for one page of data.

  1. change the model to Catalyst::Model::CDBI::Sweet. This step is well covered in the documentation.
    1. modify the template for the list
      • change the line <th>[% column %]</th> to <th>[% order_by_column_link(column) %]</th>. This uses a function we put on the stash in the controller - covered later
      • change the line [% FOR object = table_class.retrieve_all %] to [% FOR object = objects %] - we put objects on the stash in the controller
    2. modify the controller
      • add function
        use URI::Escape;
        use HTML::Entities;
        
        sub create_col_link {
            my ( $c, $column, $params, $table ) = @_;
            if(($params->{order} eq $column) and !$params->{o2}){
                $params->{o2} = 'desc';
            }else{
                delete $params->{o2};
            }
            $params->{order} = $column;
            delete $params->{page};        # just in case you'll use paging sometime
            my $addr;
            for my $key (keys %$params){
                $addr .= "&$key=" . $params->{$key};
            }
            $addr = uri_escape($addr, q{^;/?:@&=+\$,A-Za-z0-9\-_.!~*'()} );
            $addr = encode_entities($addr, '<>&"');
            my $result = '<a href="' . $c->req->{base} . $table . '/list?';
            $result .= $addr . '">' . $column . '</a>';
            if($column eq $c->form->valid->{order}){
                if($c->form->valid->{o2}){
                    $result .= "&darr;";
                }else{
                    $result .= "&uarr;";
                }
            }
            return $result;
        }
        
      • modify the list controller:
        sub list : Local {
            my ( $self, $c ) = @_;
            $c->form( optional => [ qw/order o2/ ] );
            $c->stash->{valid} = $c->form->valid;
            my $order = $c->form->valid->{order};
            $order .= ' DESC' if $c->form->valid->{o2};
            $c->stash->{objects} = [ Party::M::CDBI::Declaration->retrieve_all(
                { order_by => $order} ) ];
            $c->stash->{template} = 'Declaration/list.tt';
            $c->stash->{order_by_column_link} = sub {
                my $column = shift;
                my %params = %{$c->form->valid};
                return create_col_link($c, $column, \%params, 'declaration');
            };
        }
        

Substitute your model and table name in the place where I use Declaration, e.g. Party::M::CDBI::Declaration, 'Declaration/list.tt', 'declaration'.

That's all.


Frankly, I think this should be a Helper - but I have no time to figure out how to write a Helper.