несколько GridView на странице для одной модели

Перекопал документацию и примеры но так и не могу найти КАК сделать.

Обычно описано как выводить НЕСКОЛЬКО таблиц в один грид а у меня задача противоположная ОДНУ таблицу в несколько гридов.

Суть: на странице во вьюхе выводится несколько виджетов GridView использующие ОДНУ таблицу описанную одной моделью (ТАБЛИЦА-1).

Виджеты вывожу в цикле подключая через renderPartial отдельный файлик.

ТАБЛИЦА-1 - справочник источник записей для выбора (использую колонку чекбоксов для выбора нужных записей).

Проблема в том, что модель одна и таже, потому и поля в таблицах грид имеют одинаковые имена и соответственно имя поля получаемое в контроллере привязано к модели таблицы (в формате ИМЯ_МОДЕЛИ[ИМЯ_ПОЛЯ].

В итоге когда например в первой табличке грид я использую фильтр записей (в шапке таблицы ввожу значение) и нажимаю ентер, то на сервер отправляются поля шапки ВСЕХ грид таблиц страницы

и поскольку они имеют одинаковые имена то введенное значение затирается значениями последней таблички грид.

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

Вот и вопрос А КАК управлять этим именем???? или как решить проблему? Не создавать же руками кучу моделей для каждой грид таблички, если их будет много то это тоскливо (((.

Пробовал цеплять приставку (ИД грида) к имени полей но тогда ругается что такого поля нет в модели.

Возможно все банально решается, но как не пойму.

Фрагмент скриптов как все это крутится:


в контроллере обработчик запроса на фильтрацию записей:




/**

 * Обновление Grid таблицы после Ajax запроса

 *

 * @param string $id - ID выбраной записи

 * @param string $table - имя выбраной таблицы

 */

public function actionUpdate_grid_ajax()

{

	//адрес возврата

	//$urlRefer = $_SERVER['HTTP_REFERER'];

	$urlRefer = Yii::app()->sesion->getParam('urlRef');

	

	$nameTable = Yii::app()->request->getParam('table');

	$nameModelForm = Yii::app()->request->getParam('nameModelForm');

	$nameFieldForm = Yii::app()->request->getParam('nameFieldForm');

	$idRow = Yii::app()->request->getParam('id');

	$idTableGrid = Yii::app()->request->getParam('idGrid');

	$ajaxUrl = Yii::app()->request->getParam('ajaxurl');

	

	$arrayRequestCheckBoxes = Yii::app()->request->getParam($idTableGrid);

	$arrayCheckBoxes = $arrayRequestCheckBoxes['check_boxes_id'];

	

	//подключение модели  ТАБЛИЦЫ

	$nameModelTable = strtolower($nameTable);

	$nameModelTable = ucfirst($nameModelTable); //имя модели ТАБЛИЦЫ

	$modelTable = new $nameModelTable; //модель ТАБЛИЦЫ

	

	//подключение модели  ФОРМЫ

	$modelForm = new $nameModelForm;

	

	//массив настроек полей ФОРМЫ

	$arraySetingsFieldsForm = $modelForm->fieldsSettings();

	

	//подключение модели  таблицы источника

	$nameTableSource = $arraySetingsFieldsForm[$nameFieldForm]['tableSource'];

	$nameModelSource = ucfirst($nameTableSource);

	$modelSource = new $nameModelSource;

	

	//массив описания настроек полей таблицы источника

	$arraySetingsFieldsTableSource = $modelSource->fieldsSettings();

	

	//массив  полученных данных фильтра сортировки записией таблицы источника

	$arrayParamRequestModelSource = array();

	

	//формируем условие поиска

	$criteriaRowsSource = new CDbCriteria;

	

	//вводим в модель данные  фильтра столбцов таблицы Grid

	if (is_array($arrayParamRequestModelSource)) {

		foreach ($arrayParamRequestModelSource as $nameFieldSource => $valueField) {

			if ($valueField != '' && !is_null($valueField)) {

				if ( ($arraySetingsFieldsTableSource[$nameFieldSource]['settings']['type'] == TYPE_FIELD_FORM_TEXT)

				|| ($arraySetingsFieldsTableSource[$nameFieldSource]['settings']['type'] == TYPE_FIELD_FORM_TEXTAREA)

				){

					$criteriaRowsSource->compare($nameFieldSource, $valueField, true, 'LIKE');

				}

				else {

					$criteriaRowsSource->compare($nameFieldSource, $valueField);

				}

			}

		}

	}

	

	//добавляем условия  выбора  записей

	$listValue = $modelSource->getListSource(

			$arraySetingsFieldsForm[$nameFieldForm]['tableValueFilter'], //таблица источник значения

			$arraySetingsFieldsForm[$nameFieldForm]['fieldValueFilter'], //поле источник значения

			$idRow

	); //массив список значений для выбора

	

	$modeSelect = $arraySetingsFieldsForm[$nameFieldForm]['modeSelectFilter'];

	//

	if ($modeSelect == CODE_ENABLE) {

		//селект выбранных

		$criteriaRowsSource->addInCondition(FIELD_ID, explode(",", $listValue));

	}

	else {

		//исключение выбранных

		$criteriaRowsSource->addNotInCondition(FIELD_ID, explode(",", $listValue));

	}

	

	$nameFieldPageCount = 'pageCount_'.$nameFieldForm; //имя  поля выбора числа записей в списке

	$sessionPageCount = Yii::app()->session->get($nameFieldPageCount);

	

	//выбранные записи из талицы источника

	$dataProviderSource = new CActiveDataProvider(

			$nameTableSource,

			array(

					'criteria' => $criteriaRowsSource,

					'pagination'=>array(

							'pageSize' => (!is_null($sessionPageCount)) ? $sessionPageCount : ConfigSite::$_defPageCount,

					),

			)

	);

	//вывод  таблицы записей из БД

	echo $this->renderPartial('/admintable/_sel_rows_grid',

			array(

					'arrayData'=>array(

							'dataProvider' => $dataProviderSource, //выбранные записи из таблицы источника

							'model'        => new $modelSource,  //модель талицы источника данных

							'table'        => $modelTable->tableName(),  //имя таблицы сохранения записи

							'idRow'        => $idRow,  //ID записи редактируемой в форме

							'idTableGrid'  => $idTableGrid, //ID Таблицы Grid

							'ajaxUrl' 	   => $ajaxUrl, //URL обработчика Ajax обновления Grid

					)

			)

			, false, true

	);

}



вызов в основном файле вьюхи (в цикле) файлика: _sel_rows_grid.php




//вывод  таблицы записей из таблицы БД

echo $this->renderPartial(

	'/admintable/_sel_rows_grid', 

	array(

		'arrayData'=>array(

			'dataProvider' => $dataProviderSource, //выбранные записи из таблицы источника

			'model'        => new $modelSource,  //модель талицы источника данных

			'table'        => $modelTable->tableName(),  //имя таблицы сохранения записи

			'idRow'        => $modelForm->id,  //ID записи в таблице сохранения записи

			'idTableGrid'  => $idTableGrid, //ID Таблицы Grid

			'ajaxUrl' 	   => $ajaxUrl, //URL обработчика Ajax обновления Grid

		)

	)

);



Подключаемый файлик: _sel_rows_grid.php





<?php

/**

 *  Шаблон таблицы выбора записей в формате  Grid таблицы

 * 

 */


//Входные данные:

$arrayData = $arrayData; //массив входных данных 




$model = $arrayData['model']; //модель текущей талицы

$dataProvider = $arrayData['dataProvider']; //выбранные записи из таблицы текущей моделис учетом фильтра

$idTableGrid = $arrayData['idTableGrid']; //ID Таблицы Grid

$tableSave = $arrayData['table']; //имя таблицы сохранения записи

$idRowTableSave = $arrayData['idRow']; ////ID записи в таблице сохранения записи

$ajaxUrl = $arrayData['ajaxUrl']; //URL обработчика Ajax обновления Grid


$arraySettingsTable = $model->tableSettings(); //массив описания настроек текущей таблицы

$nameTable = $arraySettingsTable['name']; //имя таблицы в БД


//массив описания настроек полей таблицы

$arraySetingsFields = $model->fieldsSettings();


//массив список порядка отображения полей

$arrayNameFieldView = ($arraySettingsTable['settings']['select']['fields'] != '') ? $arraySettingsTable['settings']['select']['fields'] : array();


//формирование массива списка отображаемых полей таблицы с учетом порядка отображения

if (count($arrayNameFieldView) == 0) {

	foreach ($arraySetingsFields as $nameField => $arrayParamField)

	{

		$arrayNameFieldView[] = $nameField;

	}

}


//СКРИПТ управления активации Датапикера (при ОБНОВЛЕНИИ СТРАНИЦЫ)

$datePickerUpdate = NULL;


//формирование массива описания полей для таблицы Grid

$arrayColumnsTable = array();


//добавляем колонку поля чекбокса

$arrayColumnsTable[] = array(

	'id'=>$idTableGrid.'_check_boxes',

	'checked'=>"0", //значение по умолчанию (0-не помечена)

	'class'=>'CCheckBoxColumn', //используем стандартные CCheckBoxColumn элементы Yii

	'selectableRows' => 2, // из какого по счету столбца брать значения для поля value

	'checkBoxHtmlOptions' => array('class' => 'checkclass', 'name'=>$idTableGrid.'[check_boxes_id][]'),

	'htmlOptions'=>array('class'=>'group-checkbox-column'),

);


?>


<?php

//перебор имен полей для колонок таблицы

foreach ($arrayNameFieldView as $key => $nameField) {

	//массив настроек текущего поля таблицы

	$arrayParamField = $arraySetingsFields[$nameField];

	

	//общие пераметры для всех полей

	$arrayParamColumnsTable = array(

		'name' => $arrayParamField['name'], //имя поля в таблице БД 

		'header' => $arrayParamField['label'], //имя Колонки для поля

		//поле фильтра

		'filter' => $model->$nameField,//'', // оставляем фильтр по УМОЛЧАНИЮ пустым 

		'htmlOptions' => $arrayParamField['settings']['htmlOtions'], //HTML опции форматироывания поля по умолчанию

	); 

	

	//вывод для поля типа 'select'

	if ( $arrayParamField['settings']['type'] == 'select') {

		//замена  отображаемого значения Название значения  вместо ID значения для  полей содержащих ID записи из справочника

		$arrayParamColumnsTable['value'] = '$data->convert_IdValue("'.$arrayParamField["settings"]["table"].'", "title", "$data->'.$arrayParamField['name'].'")';

		

		// генерируем фильтр просто подставив обычный массив состоящий из пар ID=>наименование

		// ВАЖНО!!! код не нужно указывать в кавычках как в value!!!!

		$arrayParamColumnsTable['filter'] =  $arrayParamField['settings']['listData'];

	}

	

	//вывод для поля типа 'data'

	if ( $arrayParamField['settings']['type'] == TYPE_FIELD_FORM_DATE) {

		// + не забудьте указать в своих скриптах код afterAjaxUpdate для работы фильтра даты

		$arrayParamColumnsTable['filter'] =  $this->widget(

			'zii.widgets.jui.CJuiDatePicker', 

			array(

				'model' => $model,

				'attribute' => $nameField,

				'language' => 'ru',

				'options' => array(

					'showAnim' => 'fold',

					'dateFormat' => 'yy-mm-dd',

					'changeMonth' => 'true',

					'changeYear' => 'true',

					'showButtonPanel' => 'true',

				),

				'htmlOptions' => array(

					'id' => $nameField,

					'size' => '10',

				),

			),

			true

		);

		$datePickerUpdate = "function() {

			jQuery('#".$nameField."').datepicker(

				jQuery.extend(

					jQuery.datepicker.regional['ru'], {

						'showAnim':'fold',

						'dateFormat':'yy-mm-dd',

						'changeMonth':'true',

						'showButtonPanel':'true',

						'changeYear':'true'

					}

				)

			);

		}";

	}

	

	//вывод для поля типа 'datetime'

	if ( $arrayParamField['settings']['type'] == TYPE_FIELD_FORM_DATETIME) {

		$arrayParamColumnsTable['filter'] =  '';

	}

	

	//вывод для поля СТАТУС

	if ($arrayParamField['name'] == 'status_id') {

		$arrayParamColumnsTable['class'] = "ext.Status_id"; //обработчик значения поля

	}

	//сохраняем итоговый блок описания столбца таблицы

	$arrayColumnsTable[] = $arrayParamColumnsTable;

}


//массив описания настроек кнопок

$arrayButtons = array();


//массив списка шаблонов используемых кнопок

$template = array();


//массив описания кнопок управления записью

$arraySettingsButtonRow = array(

 	'info' => array(

 		'label'=>'просмотреть',

 		'imageUrl'=>ICON_VIEW_32,

 		'options'=>array('style'=>"margin-left:5px;", 'title'=>'Просмотреть запись'),

 		'url'=>'Yii::app()->createUrl("admintable/table_view/table/$data->code")',

 	),

);


if (is_array($arraySettingsButtonRow) && (count($arraySettingsButtonRow)>0) ){

	//формируем массив описания кнопок для Grid

	foreach ($arraySettingsButtonRow as $codeButton => $arrayParamButton) {

		if ( !isset($arraySettingsTable['settings'][$codeButton]['status'])

		|| ((isset($arraySettingsTable['settings'][$codeButton]['status']))

				&& ($arraySettingsTable['settings'][$codeButton]['status'] == TRUE)

		)){

			$arrayButtons[$codeButton] = $arrayParamButton;

			$template[] = $codeButton;

		}

	}

	

	//формирование строки списка шаблонов кнопок

	$templateList = '';

	foreach ($template as $key => $val) {

		$templateList .= '{'.$val.'}'; 

	}

	

	//Кнопки управления записью

	$arrayColumnsTable[] =	array(

		'class'              => 'CButtonColumn',

		'header'             => 'Управление',//наименование колонки

		'htmlOptions'        => array('style'=>'text-align: center; width:150px;' ),

		'template'           => $templateList, //строка список шаблонов кнопок

		'buttons'            => $arrayButtons,

	 );

}


//Дополнительная Настройка офрмления полей отображаемой таблицы

if(isset($arrayColumnsTable['id'])) {

	//замена настроек по умолчанию

	$arrayColumnsTable['id']['htmlOptions'] = array('style'=>'text-align: center; width:50px; font-weight: bold; font-size: 18px;');

}

 

//вывод  таблицы записей из БД 

$this->widget('zii.widgets.grid.CGridView', 

	array(

		'id' => $idTableGrid,

		

		//обновление таблицы после Ajax запроса

		'ajaxUpdate' => true,

		

		//URL  обработчика запроса обновления таблицы (полсе фильтрации)

		'ajaxUrl' => array($ajaxUrl),

		

		// источник данных		

		'dataProvider' => $dataProvider,


		// фильтр

		'filter' => $model,

		

		//Устанавливаем позицию фильтра

		'filterPosition' => 'body', //под названием столбца 

		

		// текст описывающий общее количество элементов и количество элементов на текущей странице пагинатора

		'summaryText' => "Записи {start}&mdash;{end} из {count}",

		

		// текст выводимый при отсутствии записей в БД или когда все записи не удовлетворяют значениям фильтров

		'emptyText' => 'Записи не найдены',


		// заголовок пагинатора

		'pager'=>array(

				'header'=>'Навигация: '

		),


		// при каждом обновлении запускаем jQuery скрипт для датапикера

		'afterAjaxUpdate' => $datePickerUpdate,

		

		//массив описания и настроек столбцов, которые должны выводиться

		'columns' => $arrayColumnsTable,

	)

);



Если честно довольно сложно понять что вы хотите реализовать, но насколько понял я - вы придумали велосипед. Все намного проще, главное понять суть работы грида и фильтров.

  1. Вы в вью передаете инстанс модели для вашей таблицы, а не массивы с dataProvider.

  2. В гридах используете:




'dataProvider'=>$model->searchForGrid1()

....

'dataProvider'=>$model->searchForGrid2()

....

'dataProvider'=>$model->searchForGrid3()



Собственно в этих функциях в модели и делаете фильтрацию какую вам необходимо. Там где не нужно учитывать параметры - не учитывайте. Насколько я понимаю они должны быть разные, иначе смысла дублировать информацию нет.

  1. Параметры пушите как обычно, в контроллере:



    public function actionIndex()

    {

        $model = new MyModel('search');

        $model->unsetAttributes();

        if (isset($_GET["MyModel"]))

            $model->attributes = $_GET["MyModel"];

       

        $this->render("index",array(

            'model' => $model,

        ));

    }



Собственно говоря как то так, вся логика фильтрации в модели, во вью только гриды.

Времени писать код сейчас нет, но идея надеюсь ясна ::)

Спасибо за совет. Идея ваша ясна но она не подходит из за того что нужно в модели описывать функцию для каждого грида а их количество может быть динамическим (потому и делаю гриды в цикле используя один настраиваемый динамически шаблон грида). Поэтому и использую ОДНУ функцию ДИНАМИЧЕСКОГО формирования ОЧЕРЕДНОГО грида но вот тут и проблема КАК различить в этой функции от какого грида пришел запрос на фильтрацию записей. Сейчас получается что виден запрос только от ПОСЛЕДНЕГО грида (в пост запросе приходящем на сервер с грид таблицы - имя формы с параметрами фильтрации у всех гридов ОДИНАКОВО!!! (грид автоматом цепляет к именам полей фильтра приставку имени модели источника данных грида ) и как его задать разным не знаю ((((). Если задавать разные имена этой самой приставки (а как следствие - формам отправляемым гридами при фильтрации в столбцах , то проблема решается). Но как их задать?????

А вообще задача стоит что есть в таблице БД поля которые содержат список ID записей таблицы справочника. В форме для таких полей отображается ДВЕ грид таблицы. Из справочника необходимо кроме ID еще отображать несколько полей из таблицы справочника и в гриде это делать наглядее чем просто использовать, например, блок полей чекбоксов. Таблицы грид привязаны к модели таблицы справочника ка источнику записей. В одном гриде отображаются уже ВЫБРАННЫЕ записи справочника, в другом гриде ЕЩЕ НЕ выбранные. Когда записей в справочнике много возникает необходимость пользоваться фильтрацией записей грид и вот эта фильтрация и не получается из за проблемы различения от какой таблицы грид запрос на фильтрацию.

Всеравно непонятно, нужно что то проще.

Все таки нужно не передавать готовый dataProvider, а формировать его в модели. То что у вас в контроллере - практически все должно быть в модели:




//формируем условие поиска

        $criteriaRowsSource = new CDbCriteria;

        

        //вводим в модель данные  фильтра столбцов таблицы Grid

        if (is_array($arrayParamRequestModelSource)) {

                foreach ($arrayParamRequestModelSource as $nameFieldSource => $valueField) {

                        if ($valueField != '' && !is_null($valueField)) {

                                if ( ($arraySetingsFieldsTableSource[$nameFieldSource]['settings']['type'] == TYPE_FIELD_FORM_TEXT)

                                || ($arraySetingsFieldsTableSource[$nameFieldSource]['settings']['type'] == TYPE_FIELD_FORM_TEXTAREA)

                                ){

                                        $criteriaRowsSource->compare($nameFieldSource, $valueField, true, 'LIKE');

                                }

                                else {

                                        $criteriaRowsSource->compare($nameFieldSource, $valueField);

                                }

                        }

                }

        }

        

        //добавляем условия  выбора  записей

        $listValue = $modelSource->getListSource(

                        $arraySetingsFieldsForm[$nameFieldForm]['tableValueFilter'], //таблица источник значения

                        $arraySetingsFieldsForm[$nameFieldForm]['fieldValueFilter'], //поле источник значения

                        $idRow

        ); //массив список значений для выбора

        

        $modeSelect = $arraySetingsFieldsForm[$nameFieldForm]['modeSelectFilter'];

        //

        if ($modeSelect == CODE_ENABLE) {

                //селект выбранных

                $criteriaRowsSource->addInCondition(FIELD_ID, explode(",", $listValue));

        }

        else {

                //исключение выбранных

                $criteriaRowsSource->addNotInCondition(FIELD_ID, explode(",", $listValue));

        }

        

        $nameFieldPageCount = 'pageCount_'.$nameFieldForm; //имя  поля выбора числа записей в списке

        $sessionPageCount = Yii::app()->session->get($nameFieldPageCount);

        

        //выбранные записи из талицы источника

        $dataProviderSource = new CActiveDataProvider(

                        $nameTableSource,

                        array(

                                        'criteria' => $criteriaRowsSource,

                                        'pagination'=>array(

                                                        'pageSize' => (!is_null($sessionPageCount)) ? $sessionPageCount : ConfigSite::$_defPageCount,

                                        ),

                        )

        );



Вот эта часть должна быть в модели, контроллер ничего об этом не должен знать.

Атрибуты присваивайте масс ассигном:




$nameTable = Yii::app()->request->getParam('table');

        $nameModelForm = Yii::app()->request->getParam('nameModelForm');

        $nameFieldForm = Yii::app()->request->getParam('nameFieldForm');

        $idRow = Yii::app()->request->getParam('id');

        $idTableGrid = Yii::app()->request->getParam('idGrid');

        $ajaxUrl = Yii::app()->request->getParam('ajaxurl');



Если таких полей нет в таблице, обьявите их public и добавьте все в safe (‘on’=>‘search’).

Собственно говоря так как фильтры различны - сделайте точку входа.




'dataProvider' => $model->entrance()



Насколько я понял в модели есть параметр в зависимости от которого и идет различие в гридах, тогда во входе:




public function entrance()

{

    if ($this->param == 1)

        return $this->getDPForGrid1()

    else return $this->getDPForGrid2() 

}



Если же нет, передавайте тип грида из вью.

Собственно говоря в этих функциях и делайте фильтрацию(поиск) необходимых значений.

Да и кстати:




//вывод  таблицы записей из БД

        echo $this->renderPartial('/admintable/_sel_rows_grid',

                        array(

                                        'arrayData'=>array(

                                                        'dataProvider' => $dataProviderSource, //выбранные записи из таблицы источника

                                                        'model'        => new $modelSource,  //модель талицы источника данных

                                                        'table'        => $modelTable->tableName(),  //имя таблицы сохранения записи

                                                        'idRow'        => $idRow,  //ID записи редактируемой в форме

                                                        'idTableGrid'  => $idTableGrid, //ID Таблицы Grid

                                                        'ajaxUrl'          => $ajaxUrl, //URL обработчика Ajax обновления Grid

                                        )

                        )

                        , false, true

        );



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

Данную конструкцию встраивайте уже во вью, и в ней делайте renderPartial.

Попробую реализовать Ваши советы. Жаль что так и не услышал ни от кого ответа по поводу задания приставки имени (yii добавляет имя модели источника данных) полей фильтра передаваемые на сервер ((((((((((( видать никто не знает …