Formulario con Select2 Kartik Múltiple

En esta entrada les muestro como modificar el formulario para que podamos ingresar múltiples elementos en el selector y como guardar en el modelo: 

1.- Modificar el formulario colocando los selectores:

 <?=  $form->field($model, 'author_id')->widget(Select2::classname(), [

    'data' => ArrayHelper::map(Author::find()->all(), 'id', 'name'),

    'theme' => Select2::THEME_BOOTSTRAP,

    'size' => Select2::LARGE,

    'options' => ['placeholder' => Yii::t('app', 'Select...')],

    'pluginOptions' => [

        'allowClear' => true

    ],

]);

     ?>


   <?=  $form->field($model, 'bookArray')->widget(Select2::classname(), [

    'data' => ArrayHelper::map(Book::find()->all(), 'id', 'name'),

    'theme' => Select2::THEME_BOOTSTRAP,

    'size' => Select2::LARGE,

    'options' => ['placeholder' => Yii::t('app', 'Select...')],

    'pluginOptions' => [

        'multiple' => true,

        'allowClear' => true

    ],

]);

     ?>


    <?php echo $form->errorSummary($model) ?>  // Esto nos permite mostrar en la parte de abajo del formulario los errores al guardar.


2.- Añadir los use:

use yii\helpers\ArrayHelper;

use kartik\select2\Select2;

use backend\modules\bookstore\models\Author\Author;

use backend\modules\bookstore\models\Book\Book;


3.- En el modelo en la parte de arriba, la variable virtual:

 public $bookArray;

4.- Añadir en las rules:

  [['author_id', 'bookArray'], 'required'],

5.- Añadir en el label:

 'bookArray' => Yii::t('app', 'Books'),

6.- Añadir en el modelo:

public function saveBookArray()

{

    AuthorBook::deleteAll(['author_id'=>$this->author_id]);

    foreach ($this->bookArray as $value) {

        $model = new AuthorBook();

        $model->author_id = $this->author_id;

        $model->book_id = $value;

        $model->bookArray = $this->bookArray;

        if(!$model->save()){

            $model->getErrors();

            $this->addErrors($model->getErrors());

            return false;  

        }

    }

    return true;

}

7.- Añadir en el modelo:

public function afterFind() {

        parent::afterFind();

        $this->bookArray = array_column(Yii::$app->db->createCommand('SELECT book_id  

                           FROM author_book 

                           WHERE author_id = "'.$this->author_id.'" 

                           ')

                           ->queryAll(),'book_id');

}


o en caso de que no necesitemos que siempre se cargue el bookArray añadimos esta otra variante:

public function getArrayValue(){

    $this->bookArray = array_column(Yii::$app->db->createCommand('SELECT book_id  

                           FROM author_book 

                           WHERE author_id = "'.$this->author_id.'" 

                           ')

                           ->queryAll(),'book_id');

}


8.- Modificar el actionCreate en el controller:

public function actionCreate()

{

    $model = new AuthorBook();


    if ($model->load(Yii::$app->request->post()) && $model->saveBookArray()) {

        return $this->redirect(['index']);

    }


    return $this->render('create', [

        'model' => $model,

    ]);

}


9.- Modificar el actionUpdate en el controller:


public function actionUpdate($id)

{

    $model = $this->findModel($id);

    $model->getArrayValue();  // En caso de que no se ponga el afterfind y utilicemos la otra variante

    if ($model->load(Yii::$app->request->post()) && $model->saveBookArray()) {

        return $this->redirect(['index']);

    }


    return $this->render('update', [

        'model' => $model,

    ]);

}


Pueden ver los detalles de la implementación en mi canal de YouTube: https://youtu.be/3SFs-JLFSL0





Comentarios

Entradas populares de este blog

AdminLTE3 integración Yii2

RBAC Yii2 utilizando la extensión "yii2mod/yii2-rbac": "*"

Integración AdminLTE2 Yii2