2

I would like to change the the labels of pages in Yii.

I used Zii.widegt.CListView to show the list of items. The default structure of yii pagination is [previous] 1 2 4 5 6 7 [next] required structure is < 1....10 11 12 13 14 ....40 >.

I read "How can I customize the labels for the pager in Yii?" which is helpful, but how can I show the firstPageLabel as page number 1 instead of << and lastPageLabel as 40 instead of >>.

Community
  • 1
  • 1
kand
  • 21
  • 1
  • 3

2 Answers2

3

If you can't find a way to pass in the total item count (i.e. 40) to the lastPageLabel override, you will need to override the CLinkPager class to have this work automatically. The $lastPageLabel is static in the current implementation and does not provide access to variables like "itemCount". You can see the code:

$buttons[]=$this->createPageButton($this->lastPageLabel,$pageCount-1,self::CSS_LAST_PAGE,$currentPage>=$pageCount-1,false);

It just echos $this->lastPageLabel, which is static text.

If you make a new pager (called, say, MyLinkPager), use it like so:

$this->widget('zii.widgets.CListView', array(
        'dataProvider' => $categoryProjects,
        'itemView'     => '_itemDetailsView',
        'ajaxUpdate'   => false,
        'pager'        => array(
                            'class'          => 'MyLinkPager', // here is your pager
                            'firstPageLabel' => '<<',
                            'prevPageLabel'  => '<',
                            'nextPageLabel'  => '>',
                            'lastPageLabel'  => '>>',
                          ),
    ));
thaddeusmt
  • 15,410
  • 9
  • 67
  • 67
2

You will have to create your own class that derives from CLinkPager. Ultimately, what you want to achieve is to change the line that thaddeusmt mentions, inside CLinkPager::createPageButtons:

$buttons[]=$this->createPageButton($this->lastPageLabel /* the rest doesn't matter */);

to do the equivalent of

$buttons[]=$this->createPageButton($pageCount /* the rest doesn't matter */);

Now obviously the direct way of doing this is by overriding createPageButtons, but that's not a trivial method and if you do override it completely, you risk your pager becoming "out of sync" with code on later versions of Yii. So let's look for alternatives.

Alternatives

(you might want to skip this part if you 're only interested in the solution)

One alternative would be to override the method, have it call the standard implementation and then simply change what you need to change:

protected function createPageButtons() {
    $buttons = parent::createPageButtons(); // Yii's implementation
    array_pop($buttons); // remove last item, which is the link for the last page

    $buttons[]=$this->createPageButton($this->getPageCount() /* the rest unchanged */);
    return $buttons;
}

That's better, but it still involves copy/pasting code so your implementation needs to keep that part in sync with future Yii releases. Can we do better than that? It turns out that yes. Here's the method CLinkPager::run:

public function run()
{
    $this->registerClientScript();
    $buttons=$this->createPageButtons();
    if(empty($buttons))
        return;
    echo $this->header;
    echo CHtml::tag('ul',$this->htmlOptions,implode("\n",$buttons));
    echo $this->footer;
}

As you see, CLinkPager doesn't really do a lot other than call createPageButtons. So you could override run and dynamically set the value of $this->lastPageLabel before letting Yii's code run, like this:

public function run()
{
    $this->lastPageLabel = $this->getPageCount();
    parent::run();
}

Well, this is nice. We managed to achieve the goal by overriding just one method and writing two lines of code. As an added bonus, there's nothing in our code that needs to be kept in sync with Yii if the implementation of CLinkPager changes in the future.

On the other hand, all of these solutions introduce an impurity that could be problematic: when someone writes a view that uses our custom pager class, they might not know that we are actually overriding the value of lastPageLabel! Imagine the "why is it not outputting the label I 'm telling it to?" confusion.

A really nice solution

Fortunately, you can have your pie and eat it too by overriding CLinkPager::init like this:

public function init()
{
    // "Hijack" the default values for properties that the user did not set.
    // This allows the user to still override this if they want to.
    if($this->nextPageLabel===null)
        $this->nextPageLabel='<';
    if($this->prevPageLabel===null)
        $this->prevPageLabel='>';
    if($this->firstPageLabel===null)
        $this->firstPageLabel='1';
    if($this->lastPageLabel===null)
        $this->lastPageLabel=$this->getPageCount();

    // and let Yii do the rest like it always does
    parent::init();
}

You can then configure your view to use this pager, and everything will work just fine without any further ado:

'pager' => array('class' => 'CustomLinkPager'),
Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806