Pull to refresh

Удобный «паджинатор»

Reading time3 min
Views3.8K
Некоторое время назад озадачился поиском решения, которое позволило бы заменить стандартный «паджинатор» (CLinkPager) Yii на такой, который бы вместо номеров страниц писал что-то более внятное. Скажем, первые символы значений полей на последующих страницах. Не нашел и решил написать свой.



Крайне неудобно переключаться между нумерованными страницами, скажем, в списке пользователей. Особенно, когда список большой. Каждое переключение при поиске пользователя на 5-10 страниц, как «гадание на кофейной гуще». То перескочишь нужного пользователя, то наоборот слишком осторожничаешь и не дойдешь. Конечно, поиск помогает, но только тогда, когда точно знаешь фамилию или иные атрибуты. Даже знание имени не помогает, т.к. разных Саш, Маш, Даш, Вань может быть в таблице десятки!
Поиск готового решения, как я написал выше, ничего не дал. Может плохо искал, исправьте, если не прав.

Задача


Пришлось изучать строение CLinkPager и писать свой класс «паджинатора».
Требования к нему были простые:

  • отображение значений, а не номеров страниц
  • отображение значений целиком или фрагмент
  • отображение значений только определенных полей.

Отображение значений, а не номеров страниц — означает, что нужно отобразить первое значение поля каждой страницы. Иными словами, значение поля записи текущей страницы, потом значение поля записи следующей страницы (со смещением равным размеру страницы) и т.д.
Отображение значений целиком или фрагмент — означает, что вывод, например, целой фамилии в «паджинатор» неудобно. Куда удобнее вывести, скажем, первую букву, а лучше две, в общем, столько, сколько будет нужно.
Отображение значений только определенных полей — означает, что выводить в «паджинатор» кусочки значений полей типа число или дата удобства не добавит, хотя, кому как. Поэтому, надо указывать список полей, значения которых будут отображаться в «паджинаторе», а для остальных показывать обычные номера страниц.

Решение


Выяснил, что за отрисовку кнопок отвечает функция createPageButtons() класса CLinkPager. Перекрыть выборочно код создания тех или иных кнопок нельзя, поэтому решил унаследовать класс и дополнить код.

Интересно то, что базовый класс CLinkPager получается универсальным как бы «сам по себе» для любого провайдера данных. Мне же пришлось обрабатывать два класса провайдера данных: CActiveDataProvider, CArrayDataProvider. Каждый отдельно.

При работе с CActiveDataProvider получение значений с каждой страницы получаю с помощью offset:

if ($this->owner->dataProvider instanceof CActiveDataProvider)
{
	$pagesize = $this->owner->dataProvider->pagination->pagesize;
	$criteria = $this->owner->dataProvider->criteria;
	$this->owner->dataProvider->sort->applyOrder($criteria);
	$criteria->limit = 1;

	for($i=$beginPage;$i<=$endPage;++$i)
	{
		$criteria->offset = $i*$pagesize;
		$m = $this->owner->dataProvider->model->find($criteria);
		$buttons[]=$this->createPageButton(is_null($this->length) ? $m->{$field} : mb_substr($m->{$field}, 0, $this->length, 'utf-8'), $i,$this->internalPageCssClass,false,$i==$currentPage);
	}
}


При работе с CArrayDataProvider получение значений с каждой страницы получаю по индексу:

if ($this->owner->dataProvider instanceof CArrayDataProvider)
{
	$pagesize = $this->owner->dataProvider->pagination->pagesize;
	$data = $this->owner->dataProvider->rawData;
	for($i=$beginPage;$i<=$endPage;++$i)
	{
		$m = $data[$i*$pagesize];
		$buttons[]=$this->createPageButton(is_null($this->length) ? $m[$field] : mb_substr($m[$field], 0, $this->length, 'utf-8'), $i,$this->internalPageCssClass,false,$i==$currentPage);
	}
}


В классе объявил две переменные:
fields — массив имен полей для которых должны отображаться значения, а не номера страниц;
length — длина обрезки значения, если null, то целиком.

Использовать класс, например, в CGridView можно так:
'pager'=>array(	
	'class' => 'AlxdTitlePager',
	'fields'=>array('lastname','firstname','middlename','email'),
	'length'=>'2',
	'maxButtonCount'=>10,
	'firstPageLabel'=>'<<',
	'header'=>'',
	'hiddenPageCssClass'=>'disabled',
	'lastPageLabel'=>'>>',
	'nextPageLabel'=>'>',
	'selectedPageCssClass'=>'active',
	'prevPageLabel'=>'<',
	'htmlOptions'=>array('class'=>'pagination')	
)


В общем, немного обкатав код решил им поделиться. Кому интересно, может получить исходный код моего класса AlxdTitlePager безвозмездно.
Tags:
Hubs:
+1
Comments0

Articles

Change theme settings