Search code examples
phpframeworksatk4agiletoolkit

Extending the Grid UI element to link to a page


I am using Agile Toolkit for some development and would like to extend the existing Grid Control so that each row contains the data (as it does right now) but also links to a page with a query string that contains the ID. I want to be able to do something like:

$this->add('Grid', 'short-name', 'template-tag', array('page?id=', 'id'))->setModel('mydatasource');

I can currently use the following:

$this->add('Grid', 'short-name', 'template-tag')->setModel('mydatasource');

But I would like to be able to specify the page I'm linking to as a format with the field I want to pass so that clicking on anywhere on the second row:

1     Jack Johnson     Clerk
2     John Doe         Executive

Takes me to: myapp.com/page?id=2

How would I go about extending the Grid element to do that? Or do I need to extend all the way down from AbstractView or Lister?

Thanks!

Full working solution:

precacheTemplate removed the reference from row_t for the variable I defined in the html template. So I followed the existing practice, added another reset of the variable (i.e. where it sets the to ) of to - that way it stays in memory as a reference to go back to the template field inside the generic formatRow which is being overloaded from Basic Grid.

Roman had mentioned some of this before but i finally got the missing link where i had to reset.

Best way to understand is to compare line-by-line my grid and the Basic Grid (yes I know I extend from Advanced).

Hopefully that helps anyone else that has the exact same question.

On the page

$this->add('ExtendedUI_GridLinkedRow', array('dest_page'=>'home', 'name'=>'assessments'), 'assessments')
    ->setModel('GrantAssessment')
    ->addCondition('uid', 1);

GridLinkedRow.php

    <?php

class ExtendedUI_GridLinkedRow extends Grid_Advanced {

    function init(){
        parent::init();
    }

    function defaultTemplate(){
        return array('ExtendedUI/grid_linked_row');
    }

    function precacheTemplate(){
        // pre-cache our template for row
        // $full=false used for certain row init
        $row = $this->row_t;
        $col = $row->cloneRegion('col');

        // tbody -> column
        $row->setHTML('row_id','<?$id?>');
        $row->trySetHTML('odd_even','<?$odd_even?>');
        $col->setHTML('dest_link','<?$page_link?>');
        $row->del('cols');

        // thead -> column
        $header = $this->template->cloneRegion('header');
        $header_col = $header->cloneRegion('col');
        $header_sort = $header_col->cloneRegion('sort');

        // Totals -> column
        if($t_row = $this->totals_t){
            $t_col = $t_row->cloneRegion('col');
            $t_row->del('cols');
        }

        $header->del('cols');

        foreach($this->columns as $name=>$column){
            $col->del('content');
            $col->setHTML('content','<?$'.$name.'?>');

            if(isset($t_row)){
                $t_col->del('content');
                $t_col->setHTML('content','<?$'.$name.'?>');
                $t_col->trySetHTML('tdparam','<?tdparam_'.$name.'?>style="white-space: nowrap"<?/?>');
                $t_row->appendHTML('cols',$t_col->render());
            }

            // some types needs control over the td

            $col->setHTML('tdparam','<?tdparam_'.$name.'?>style="white-space: nowrap"<?/?>');

            $row->appendHTML('cols',$col->render());

            $header_col->set('descr',$column['descr']);
            $header_col->trySet('type',$column['type']);

            // TODO: rewrite this (and move into Advanced)
            if(isset($column['sortable'])){
                $s=$column['sortable'];
                // calculate sortlink
                $l = $this->api->getDestinationURL(null,array($this->name.'_sort'=>$s[1]));

                $header_sort->trySet('order',$column['sortable'][0]);
                $header_sort->trySet('sorticon',$this->sort_icons[$column['sortable'][0]]);
                $header_sort->set('sortlink',$l);
                $header_col->setHTML('sort',$header_sort->render());
            }else{
                $header_col->del('sort');
                $header_col->tryDel('sort_del');
            }

            if($column['thparam']){
                $header_col->trySetHTML('thparam',$column['thparam']);
            }else{
                $header_col->tryDel('thparam');
            }

            $header->appendHTML('cols',$header_col->render());

        }
        $this->row_t = $this->api->add('SMlite');
        $this->row_t->loadTemplateFromString($row->render());

        if(isset($t_row)){
            $this->totals_t = $this->api->add('SMlite');
            $this->totals_t->loadTemplateFromString($t_row->render());
        }

        $this->template->setHTML('header',$header->render());
    }

    function formatRow(){

        if(!$this->columns)throw $this->exception('No columns defined for grid');

        foreach($this->columns as $tmp=>$column){
            $this->current_row[$tmp.'_original']=@$this->current_row[$tmp];

            $formatters = explode(',',$column['type']);
            foreach($formatters as $formatter){
                if(!$formatter)continue;
                if(method_exists($this,$m="format_".$formatter)){
                    $this->$m($tmp,$column);
                }else throw new BaseException("Grid does not know how to format type: ".$formatter);
            }
            // setting cell parameters (tdparam)
            $this->applyTDParams($tmp);
            if($this->current_row[$tmp]=='')$this->current_row[$tmp]=' ';
        }
        $this->row_t->setHTML('page_link', $this->api->url($this->dest_page, array('id'=>$this->current_id)));
        return $this->current_row;
    }

}

For the templates:

grid_linked_row.html

<?$Misc?>
<div id="<?$_name?>" class="atk-grid">
  <div class="atk-grid-panel">
    <?quick_search?><?/?>
    <div class="atk-buttons"><?grid_buttons?><?/?></div>
  </div>
  <table width="<?table_width?>100%<?/?>">
    <?header?>
    <thead class="ui-widget-header"><tr>
        <?cols?>
        <?col?>
        <th class="ui-widget-header" nowrap    <?$thparam?>><?sort?><i  style="float: left" class="ui-icon <?$sorticon?>"></i><a href="<?$sortlink?>"><?/sort?><?descr?>Customer<?/?><?sort_del?></a><?/?></th>
        <?/col?>
        <?/cols?>
    </tr></thead>
    <?/header?>

    <tbody class="grid_body">
      <?rows?>
      <?row?>
      <tr class="<?$odd_even?>" data-id="<?$row_id?>" rel="<?$row_id?>">
        <?cols?>
        <?col?>
        <td <?$tdparam?>><a href="<?$dest_link?>"><?$content?></a></td>
        <?/col?>
        <?/cols?>
      </tr>
      <?/row?>

      <?totals?>
      <tr class="atk-grid-totals">
        <?cols?>
        <?col?>
        <td <?$tdparam?>><?$content?></td>
        <?/col?>
        <?/cols?>
      </tr>
      <?/totals?>
      <?/rows?>


    </tbody>
    <?full_table?>
    <?/full_table?>
  </table>
  <?not_found?><div class="atk-grid-notfound ui-state-highlight ui-corner-all"><i class="ui-icon ui-icon-alert float-left"></i>No Records Found</div><?/not_found?>
  <div class="atk-paginator"><?paginator?><?/?></div>
  <?hidden_forms?><?/hidden_forms?>
</div>

Solution

  • If you want to wrap all the text values of your grid inside a link, you can use the following:

    $this->add('MyGrid',array('dest_page'=>'page'), 'template-tag');
    
    
    class MyGrid extends Grid {
        function format_text($field){
            parent::format_text($field);
    
            // Wrap the value inside a link
            $this->current_row_html[$field]='<a href="'.
                $this->api->url($this->dest_page, array('id'=>$this->current_id).'">'.
                ($this->current_row_html[$field]?:
                 htmlspecialchars($this->current_row[$field],ENT_NOQUOTES,'UTF-8')).
                '</a>'
        }
    }