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
Publicar un comentario