Добавим в GRUD Gen. возм. массового удал. и изм. ч/з Ajax

Обсуждение документации. Переводы Cookbook и авторские рецепты.
Ответить
Аватара пользователя
icewill
Сообщения: 46
Зарегистрирован: 2013.07.12, 06:45

Добавим в GRUD Gen. возм. массового удал. и изм. ч/з Ajax

Сообщение icewill »

Извините, но название не влезло полностью, продублирую:
Добавление в CRUD Cenerator возможности массового удаления и изменения элементов с помощью Ajax.

Итак, если Вы еще не вносили доработки в CRUD Generator все просто. Переходим по адресу framework\gii\generators\crud\templates\default в данной папке следует заменить в файлах admin, controller полностью код на представленный ниже и создать файл _update. Заклинаю Вас :D ! Перед заменой сделайте резервное копирование папки default. Вот и все можно генерировать код для CRUD, только теперь перейдя в менеджер рядом с ссылкой "расширенный поиск" будут еще ссылки на удаление выбранных элементов и изменение данных.

Важно:
- валидация изменяемых элементов проходит под сценарием "updateall", следовательно в модели для этого сценария следует убрать проверку на обязательность ввода (required);
- при массовом изменении данных незаполненные поля не заменяются;
- и еще могут быть проблемы с кодировкой, ставим смело UTF-8.

PS: код сырой и жаждет тестирования.

admin.php

Код: Выделить всё

 <?php
/**
 * The following variables are available in this template:
 * - $this: the CrudCode object
 */
?>
<?php echo "<?php\n"; ?>
/* @var $this <?php echo $this->getControllerClass(); ?> */
/* @var $model <?php echo $this->getModelClass(); ?> */

<?php
$label=$this->pluralize($this->class2name($this->modelClass));
echo "\$this->breadcrumbs=array(
    '$label'=>array('index'),
    'Manage',
);\n";
?>

$this->menu=array(
    array('label'=>'List <?php echo $this->modelClass; ?>', 'url'=>array('index')),
    array('label'=>'Create <?php echo $this->modelClass; ?>', 'url'=>array('create')),
);

Yii::app()->clientScript->registerScript('search', "

$('.search-button').click(function(){
    $('.search-form').toggle();
    return false;
});

$('.update-button').click(function(){
    $('#update-form').toggle();
    return false;
});

$('.search-form form').submit(function(){
    $('#<?php echo $this->class2id($this->modelClass); ?>-grid').yiiGridView('update', {
        data: $(this).serialize()
    });
    return false;
});
");
?>

<h1>Журнал <?php echo $this->pluralize($this->class2name($this->modelClass)); ?></h1>

<p>
You may optionally enter a comparison operator (<b><</b>, <b><=</b>, <b>></b>, <b>>=</b>, <b><></b>
or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.
</p>

<?php echo "<?php echo CHtml::link('Расширенный поик','#',array('class'=>'search-button')); ?>"; ?> &nbsp;&nbsp;&nbsp;
<?php echo "<?php echo CHtml::link('Изменение данных','#',array('class'=>'update-button')); ?>"; ?> &nbsp;&nbsp;&nbsp;
<?php echo "<?php echo CHtml::ajaxLink('Удалить выбранные',\$this->createUrl('deletechecked'),\$this->ajaxQueryById(\$this->idLinkDeleteAll), 
            array('confirm'=>'Вы уверены, что хотите удалить выбранные элементы?','id'=>\$this->idLinkDeleteAll)); ?>"; ?>



<div class="search-form" style="display:none">
<?php echo "<?php \$this->renderPartial('_search',array(
    'model'=>\$model,
)); ?>\n"; ?>
</div><!-- search-form -->

<div id="update-form" class="search-form" style="display:none;">
<?php echo "<?php \$this->renderPartial('_update',array(
    'model'=>\$object,
)); ?>\n"; ?> 
</div><!-- update-form -->


<?php echo "<?php"; ?> $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'<?php echo $this->class2id($this->modelClass); ?>-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'selectableRows'=>2,
    'columns'=>array(
    array(
            'class'=>'CCheckBoxColumn',
        'id'=> <?php echo '$this->idCheckBoxColumn'; ?>,
        ),
<?php
$count=0;
foreach($this->tableSchema->columns as $column)
{
    if(++$count==7)
        echo "\t\t/*\n";
    echo "\t\t'".$column->name."',\n";
}
if($count>=7)
    echo "\t\t*/\n";
?>
        array(
            'class'=>'CButtonColumn',
        ),
        
    ),
)); ?>

controller.php

Код: Выделить всё

 <?php
/**
 * This is the template for generating a controller class file for CRUD feature.
 * The following variables are available in this template:
 * - $this: the CrudCode object
 */
?>
<?php echo "<?php\n"; ?>

class <?php echo $this->controllerClass; ?> extends <?php echo $this->baseControllerClass."\n"; ?>
{
       
    /**
     * @var string.
     */
    public $insertNull = 'N$';
    public $idCheckBoxColumn = 'checkboxlist';
    public $idButtonUpdateAll = 'updateall';
    public $idLinkDeleteAll = 'deleteallelements';
    
    /**
     * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
     * using two-column layout. See 'protected/views/layouts/column2.php'.
     */
    public $layout='//layouts/column2';

    /**
     * @return array action filters
     */
    public function filters()
    {
        return array(
            'accessControl', // perform access control for CRUD operations
            'postOnly + delete', // we only allow deletion via POST request
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules()
    {
        return array(
            array('allow',  // allow all users to perform 'index' and 'view' actions
                'actions'=>array('index','view'),
                'users'=>array('*'),
            ),
            array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions'=>array('create','update'),
                'users'=>array('@'),
            ),
            array('allow', // allow admin user to perform 'admin' and 'delete' actions
                'actions'=>array('admin','delete','deletechecked'),
                'users'=>array('admin'),
            ),
            array('deny',  // deny all users
                'users'=>array('*'),
            ),
        );
    }

    /**
     * Displays a particular model.
     * @param integer $id the ID of the model to be displayed
     */
    public function actionView($id)
    {
        $this->render('view',array(
            'model'=>$this->loadModel($id),
        ));
    }

    /**
     * Creates a new model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     */
    public function actionCreate()
    {
        $model=new <?php echo $this->modelClass; ?>;

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if(isset($_POST['<?php echo $this->modelClass; ?>']))
        {
            $model->attributes=$_POST['<?php echo $this->modelClass; ?>'];
            if($model->save())
                $this->redirect(array('view','id'=>$model-><?php echo $this->tableSchema->primaryKey; ?>));
        }

        $this->render('create',array(
            'model'=>$model,
        ));
    }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id the ID of the model to be updated
     */
    public function actionUpdate($id)
    {
        $model=$this->loadModel($id);

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if(isset($_POST['<?php echo $this->modelClass; ?>']))
        {
            $model->attributes=$_POST['<?php echo $this->modelClass; ?>'];
            if($model->save())
                $this->redirect(array('view','id'=>$model-><?php echo $this->tableSchema->primaryKey; ?>));
        }

        $this->render('update',array(
            'model'=>$model,
        ));
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete($id)
    {
        $this->loadModel($id)->delete();

        // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
        if(!isset($_GET['ajax']))
            $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
    }

    /**
     * Lists all models.
     */
    public function actionIndex()
    {
        $dataProvider=new CActiveDataProvider('<?php echo $this->modelClass; ?>');
        $this->render('index',array(
            'dataProvider'=>$dataProvider,
        ));
    }

    /**
     * Manages all models.
     */
    public function actionAdmin()
    {
        $object = new <?php echo $this->modelClass; ?>('updateall');
        $this->performAjaxValidation($object); 
       
       if (isset($_POST['button']) && isset($_POST['<?php echo $this->modelClass; ?>'])):
       if (isset($_POST[$this->idCheckBoxColumn])) 
        { 
        $object->unsetAttributes();
        $object->attributes = $_POST['<?php echo $this->modelClass; ?>'];
        if ($object->validate() && $this->updateAll($_POST[$this->idCheckBoxColumn],$object->attributes) == true)
        echo 'Замена прошла успешно. Подождите пока журнал обновится.';
        else echo 'Невозможно произвести замену.';
        Yii::app()->end();
        }
        else
        {
            echo 'Элементы не выбраны.';
            Yii::app()->end();
        }
        endif;
        
        $model=new <?php echo $this->modelClass; ?>('search');
        $model->unsetAttributes();  // clear any default values
        if(isset($_GET['<?php echo $this->modelClass; ?>']))
            $model->attributes=$_GET['<?php echo $this->modelClass; ?>'];

        $this->render('admin',array(
            'model'=>$model, 'object'=>$object,
        ));
    }

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer $id the ID of the model to be loaded
     * @return <?php echo $this->modelClass; ?> the loaded model
     * @throws CHttpException
     */
    public function loadModel($id)
    {
        $model=<?php echo $this->modelClass; ?>::model()->findByPk($id);
        if($model===null)
            throw new CHttpException(404,'The requested page does not exist.');
        return $model;
    }

    /**
     * Performs the AJAX validation.
     * @param <?php echo $this->modelClass; ?> $model the model to be validated
     */
    protected function performAjaxValidation($model)
    {
        if(isset($_POST['ajax']) && $_POST['ajax']==='<?php echo $this->class2id($this->modelClass); ?>-form')
        {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }
 
    
    /**
     * Массовое удаление элементов.
     */
    
    public function actionDeletechecked()
    {
     if (isset($_POST[$this->idCheckBoxColumn]))
      { 
        foreach ($_POST[$this->idCheckBoxColumn] as $id)
        $this->loadModel($id)->delete();
        echo 'Выбранные элементы успешно удалены. Подождите пока журнал обновится.';
        return;
    }
    echo 'Элементы не выбраны.';
    return;
       }
    
    /**
     * @return array возвращает настройки ajax под id элемента.
     */
    
     public function ajaxQueryById($id,$switch = 'link')
    {
        if ($id == null || !is_string($id)) return;
        if ($switch == 'submit')
        {   $data = '"button=OK&" + $(\'#<?php echo $this->class2id($this->modelClass); ?>-form, input[name="'.$this->idCheckBoxColumn.'[]"]:checked\').serialize()';
            $id = '#<?php echo $this->class2id($this->modelClass); ?>-form #'.$id;
        }   else 
        {   $data = '$(\'input[name="'.$this->idCheckBoxColumn.'[]"]:checked\').serialize()';
            $id = '#'.$id;
        }
        $array = array(
    'type'=>'post',
    'beforeSend'=>'function(){'.self::blockUnButton($id,'true').'}',
    'error'=>'function(xhr, status){alert(\'Ошибка отправки.\'); '.self::blockUnButton($id).'}',
    'data'=>'js: '.$data,
    'success'=>'function(data){$(\'#<?php echo $this->class2id($this->modelClass); ?>-grid\').yiiGridView(\'update\'); alert(data); '.self::blockUnButton($id).'}');
    return $array;   
    }
    
    /**
     * @return string генерирует код блокировки и разблокировки кнопок.
     */
    
    public static function blockUnButton($id,$block = 'false')
    {
     return ' $(\''.$id.'\').prop(\'disabled\','.$block.');';  
    }
    
    /**
     * @return boolean возвращает true если замена прошла успешно.
     */
    
    protected function updateAll($pk,$attributes)
    {
    foreach ($attributes as $key=>$value)
    if ($value == $this->insertNull) $array[$key] = null; 
    elseif ($value != null) $array[$key] = $value; 
    if ($array == null) return false;
    <?php echo $this->modelClass; ?>::model()->updateByPk($pk,$array);
    unset ($array); unset($pk);
    return true;
    }
       
}
_update.php данный файл следует создать

Код: Выделить всё

 <?php
/**
 * The following variables are available in this template:
 * - $this: the CrudCode object
 */
?>
<?php echo "<?php\n"; ?>
/* @var $this <?php echo $this->getControllerClass(); ?> */
/* @var $model <?php echo $this->getModelClass(); ?> */
/* @var $form CActiveForm */
?>

<div class="wide form">
<ul>
<b>Важно помнить:</b>
<li> Поддерживается массовое изменение данных журнала; </li>
<li> Поставьте галочки напротив элементов журнала, которые хотите изменить.</li>
<li> Незаполненные поля не будут участвовать в замене.</li>
<li> Чтобы заменить данные на null, используйте ключевое слово "<?php echo "<?php echo \$this->insertNull; ?>"; ?>".</li>
</ul>


<?php echo "<?php \$form=\$this->beginWidget('CActiveForm', array(
    'id'=>'".$this->class2id($this->modelClass)."-form',
    'enableAjaxValidation'=>true,
    'clientOptions'=>array(
        'validateOnChange'=>true,
    ),
)); 
 ?>\n"; ?>
 
 
<?php
foreach($this->tableSchema->columns as $column)
{
    if($column->autoIncrement)
        continue;
?>
    <div class="row">
        <?php echo "<?php echo ".$this->generateActiveLabel($this->modelClass,$column)."; ?>\n"; ?>
        <?php echo "<?php echo ".$this->generateActiveField($this->modelClass,$column)."; ?>\n"; ?>
        <?php echo "<?php echo \$form->error(\$model,'{$column->name}'); ?>\n"; ?>
    </div>

<?php
}
?>
    <div class="row buttons">
        <?php echo "<?php echo CHtml::ajaxSubmitButton('Изменить',\$this->createUrl(\$this->action->id),\$this->ajaxQueryById(\$this->idButtonUpdateAll,'submit'),array('id'=>\$this->idButtonUpdateAll)); ?> \n"; ?>
    </div>

<?php echo "<?php \$this->endWidget(); ?>\n"; ?>

</div><!-- update-form -->
Ответить