読者です 読者をやめる 読者になる 読者になる

Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

1つの画面で複数のpaginateを使う方法

・・・超絶めんどくさいですが、一応可能でした。こんなんでいいのかホント。

とりあえず晒しておきます。

複数利用する以上はページングするViewが複数あるわけなので、ふつーにpaginatorで吐き出すページ送りのリンクをGETで叩いちゃうと更新対象でないViewも更新されちゃうのが嫌なので、Ajaxで呼び出すようにしました。

Controllerのコード

<?php
//この2つのmodelを使うことにする
var $uses = ('User','Book');
function index() {
$photo_option = array(
    "model" =>'Photo',
    'pagination'=>'photo-pagination',
    'update'=>'photolist'
);
$book_option = array(
    "model" =>'Book',
    'pagination'=>'book-pagination',
    'update'=>'albumlist'
);
      //pagination 利用時
     if ($this->RequestHandler->isAjax()) {
        $result = $this->paginate($this->$this->passedArgs['model']); 
        if ($this->passedArgs['model'] === 'User') {
           $this->set('userlist',$result) ; 
           $this->set('user_option',$user_option);
           $this->render('/elements/userlist');
           return;
        } else {
           $this->set('booklist',$result);
           $this->set('book_option',$book_option);
           $this->render('/elements/booklist');
           return;
       }
    }  else {
           $this->set('userlist',$this->paginate('User'));
           $this->set('user_option',$user_option);
           $this->set('booklist',$this->paginate('Book'));
           $this->set('book_option',$book_option);
    }
}

Ajaxでページ送りを実装するView

<div id="userlist">
    <?php echo $this->element('photolist',array('option'=>$photo_option));?>
</div>

<div id="booklist">
    <?php echo $this->element('booklist',array('option'=>$book_option));?>
</div>

各々Element化したdivに検索条件や更新対象のdivの名前を渡します。

Ajaxで呼び出した時に更新するElement

bookilist.ctp
<?php
 <?php echo $this->element('paginator',array('option'=>$book_option));?>
 <?php foreach($booklist as $v):?>
 <?php echo $v;?>
 <?php endforeach;?>
userlist.ctp
<?php
 <?php echo $this->element('paginator',array('option'=>$user_option));?>
 <?php foreach($userlist as $v):?>
 <?php echo $v;?>
 <?php endforeach;?>

paginatorはdiv要素と更新対象のdivが違うだけなのでelement化しました。

elementからelementを呼び出しています。

Pagiinatorのelement

element/paginator.ctp
<?php
<div id="<?php echo $option['pagination']?>" class="pagination">
   <?php $paginator->options( array('url' =>$option));?>
   <?php
    if($paginator->hasPrev()) {
      echo $paginator->prev('<<前へ', array('model' => $option['model'],'class'=>'prev'));
    }
      echo $paginator->numbers(array('model' => $option['model'],'class'=>'page'));
    if($paginator->hasNext()) {
      echo $paginator->next('次へ>>', array('model' => $option['model'],'class'=>'next'));
    }
    ?>
</div>
<script type="text/javascript">
$(document).ready(function(){
    var update = "#" + "<?php echo $option['update']?>";
    var pagination = "#" + "<?php echo $option['pagination']?>";
    $(pagination + ' a').click(function() {
        var url = $(this).attr("href");
       $(update).load(url);
        return false;
		});
	});
</script>

prev,numbers,nextのoptionに'model'というキーを渡しているのがポイントです。paginate()は複数呼ばれた場合、対象のモデル毎に情報を保存しておいてくれるので、異なるpaginate()の結果に対して適切なページ数を表示してくれます。

最初はpaginatorが吐き出すページングの部分をclassにしたんですが、classだと更新対象に含まれない部分も呼ばれてしまうので、苦肉の策でID要素の中に入れてスコープを切っています。

めんどくさいなぁもう。