Select2 by kartik - selected value on update - junction table (many to many)

Problem: Select2 field is not retrieving inserted values from the database, showing "Select a location…" prompt all the time.

I have the following setup on a fresh yii2advanced project:

3 tables : user, locations, userlocations (junction table containing user_id & location_id)

Behaviours: On user/create everything works smooth, I select 2 locations, they both get inserted successfully by the foreach loop resulting in 2 rows in my junction table: user_id: 1 location_id: 1 and user_id: 1 location_id: 2 (everything fine by now)

Problem is on user/update. The select2 field is showing "Select a location…" prompt all the time instead of the inserted values from the junction table. The user/update also works as expected, deleting the old values and inserting new ones in the database, the only problem seems to be the select2 does not retrieve the inserted values and always showing the prompt.

Please check my code!

User controller:




<?php


namespace backend\controllers;


use Yii;

use backend\models\User;

use backend\models\UserSearch;

use yii\web\Controller;

use yii\web\NotFoundHttpException;

use yii\filters\VerbFilter;

use yii\helpers\ArrayHelper;


use backend\models\Locations;

use backend\models\Userlocations;


/**

 * UserController implements the CRUD actions for User model.

 */

class UserController extends Controller

{

    /**

     * @inheritdoc

     */

    public function behaviors()

    {

        return [

            'verbs' => [

                'class' => VerbFilter::className(),

                'actions' => [

                    'delete' => ['POST'],

                ],

            ],

        ];

    }


    /**

     * Lists all User models.

     * @return mixed

     */

    public function actionIndex()

    {

        $searchModel = new UserSearch();

        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);


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

            'searchModel' => $searchModel,

            'dataProvider' => $dataProvider,

        ]);

    }


    /**

     * Displays a single User model.

     * @param integer $id

     * @return mixed

     */

    public function actionView($id)

    {

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

            'model' => $this->findModel($id),

        ]);

    }


    /**

     * Creates a new User model.

     * If creation is successful, the browser will be redirected to the 'view' page.

     * @return mixed

     */

    public function actionCreate()

    {

        $model = new User();

        $locations = ArrayHelper::map(Locations::find()->all(), 'id', 'name');

        $userlocations = new Userlocations();


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


            $model->setPassword($model->password);

            $model->generateAuthKey();


            $userlocations->load(Yii::$app->request->post());


            if ($model->save() && !empty($userlocations->location_id)){

                

                foreach ($userlocations->location_id as $location_id) {

                    $userlocations = new Userlocations();

                    $userlocations->setAttributes([

                        'location_id' => $location_id,

                        'user_id' => $model->id,

                    ]);

                    $userlocations->save();

                }

            }

   

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

        } else {

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

                'model' => $model,

                'locations' => $locations,

                'userlocations' => $userlocations,

            ]);

        }

    }


    /**

     * Updates an existing User model.

     * If update is successful, the browser will be redirected to the 'view' page.

     * @param integer $id

     * @return mixed

     */

    public function actionUpdate($id)

    {

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

        $locations = ArrayHelper::map(Locations::find()->all(), 'id', 'name');

        $userlocations = new Userlocations();


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


            Userlocations::deleteAll(['user_id' => $id]);

            $userlocations->load(Yii::$app->request->post());


            if (!empty($userlocations->location_id)){

                foreach ($userlocations->location_id as $location_id) {

                    $userlocations = new Userlocations();

                    $userlocations->setAttributes([

                        'location_id' => $location_id,

                        'user_id' => $model->id,

                    ]);

                    $userlocations->save();

                }

            }


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

        } else {


            

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

                'model' => $model,

                'locations' => $locations,

                'userlocations' => $userlocations,

            ]);

        }

    }


    /**

     * Deletes an existing User model.

     * If deletion is successful, the browser will be redirected to the 'index' page.

     * @param integer $id

     * @return mixed

     */

    public function actionDelete($id)

    {

        $this->findModel($id)->delete();


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

    }


    /**

     * Finds the User model based on its primary key value.

     * If the model is not found, a 404 HTTP exception will be thrown.

     * @param integer $id

     * @return User the loaded model

     * @throws NotFoundHttpException if the model cannot be found

     */

    protected function findModel($id)

    {

        if (($model = User::findOne($id)) !== null) {

            return $model;

        } else {

            throw new NotFoundHttpException('The requested page does not exist.');

        }

    }


}



User model:


<?php


namespace backend\models;


use Yii;


/**

 * This is the model class for table "User".

 *

 * @property integer $id

 * @property string $username

 * @property string $auth_key

 * @property string $password_hash

 * @property string $password_reset_token

 * @property string $email

 * @property integer $status

 * @property integer $created_at

 * @property integer $updated_at

 */

class User extends \common\models\User

{


    public $password;


    /**

     * @inheritdoc

     */

    public static function tableName()

    {

        return 'User';

    }


    /**

     * @inheritdoc

     */

    public function rules()

    {

        return [

            [['username', 'password'], 'required'],

            [['status', 'created_at', 'updated_at'], 'integer'],

            [['username', 'password_hash', 'password_reset_token', 'email'], 'string', 'max' => 255],

            [['auth_key'], 'string', 'max' => 32],

            [['username'], 'unique', 'message' => 'Username already taken!'],

            [['email'], 'unique'],

            [['password_reset_token'], 'unique'],

        ];

    }


    /**

     * @inheritdoc

     */

    public function attributeLabels()

    {

        return [

            'id' => 'ID',

            'username' => 'Username',

            'auth_key' => 'Auth Key',

            'password_hash' => 'Password Hash',

            'password_reset_token' => 'Password Reset Token',

            'email' => 'Email',

            'status' => 'Status',

            'created_at' => 'Created At',

            'updated_at' => 'Updated At',

        ];

    }


}



User _form:


<?php


use yii\helpers\Html;

use yii\widgets\ActiveForm;

use yii\helpers\ArrayHelper;

use kartik\select2\Select2;


use backend\models\Locations;


/* @var $this yii\web\View */

/* @var $model backend\models\User */

/* @var $form yii\widgets\ActiveForm */

?>


<div class="user-form">


    <?php $form = ActiveForm::begin(); ?>


    <?= $form->field($model, 'username')->textInput(['maxlength' => true]) ?>


    <?= $form->field($model, 'password')->passwordInput(['maxlength' => true]) ?>


    <?= $form->field($model, 'email')->textInput(['maxlength' => true]) ?>


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

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

    	'size' => Select2::MEDIUM,

	    'options' => ['placeholder' => 'Select a location ...', 'multiple' => true],

	    'pluginOptions' => [

	        'allowClear' => true,

            'location_id' => $userlocations->location_id,

	    ],

	]); ?>


    <?= $form->field($model, 'status')->dropDownList(['10' => 'Active', '0' => 'Inactive']) ?>


    <div class="form-group">

        <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

    </div>


    <?php ActiveForm::end(); ?>


</div>



Finally fixed! I was using the widget wrong apparently

<?= Select2::widget([

'name' =&gt; 'Userlocations[location_id]',


'value' =&gt; &#036;location_ids, // initial value


'data' =&gt; ArrayHelper::map(Locations::find()-&gt;all(), 'id', 'name'),


'options' =&gt; ['placeholder' =&gt; 'Select a color ...', 'multiple' =&gt; true],


'pluginOptions' =&gt; [


    'tags' =&gt; true,


    'maximumInputLength' =&gt; 10


],

]); ?>

This solved my problem!