Yii Framework Forum

DropdownList to load Gridview based on Parameter


(Folumikeidowu) #1

I have this code
SearchModel

    public function searchSubject($params, $groupingId = null)
{
$query = (new \yii\db\Query())
	    ->select(['sbt.subject_id', 'sbt.subject_title', 'grp.grouping_id', 'grp.grouping_name', 'sgp.subject_grouping_id']) 
	    ->from('grouping grp')
	    ->join('INNER JOIN', 'subject_grouping sgp', 'sgp.subject_grouping_grouping_id = grp.grouping_id')
	    ->join('INNER JOIN', 'subject sbt', 'sbt.subject_id = sgp.subject_grouping_subject_id')
	    ->where([
			'sbt.is_status' => '0',
			'grp.grouping_id' => $groupingId
		   ])
	    ->orderBy('subject_title ASC');

    $dataProvider = new ActiveDataProvider([
        'query' => $query, 
    ]);

    $this->load($params);

    if (!$this->validate()) {
        return $dataProvider;
    }

    return $dataProvider;
}   

Controller

    public function actionCreate()
{
    $model = new Exam();
$searchModel = new SubjectSearch();
$dataProvider = $searchModel->searchSubject(Yii::$app->request->queryParams);

if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
    	\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    	return ActiveForm::validate($model);
   	}
if ($model->load(Yii::$app->request->post())) {
	
		$model->attributes = $_POST['Exam'];
		$model->save();
		return $this->redirect(['index']);
   	}
    else {
        return $this->render('create', [
            'model' => $model,
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider,
        ]);
    }
}

View

        <div class="col-xs-12 col-sm-4 col-lg-4">    
      <?= $form->field($model, 'exam_group_id')->widget(Select2::classname(), [
            'data' => ArrayHelper::map(app\models\Grouping::find()->all(),'grouping_id','grouping_name'),
            'language' => 'en',
            'options' => ['placeholder' => '--- Select Grouping ---'],
            'pluginOptions' => [
                'allowClear' => true
            ],
        ]); ?> 
    </div>

<div class="col-xs-12" style="padding-top: 10px;">
   <div class="box">
      <div class="box-body table-responsive">
       <div class="subject-index">
        <?= GridView::widget([
	'dataProvider' => $dataProvider,
	'filterModel' => $searchModel,
	'summary'=>'',
	'columns' => [
	    ['class' => 'yii\grid\SerialColumn'],
	    'subject_title',
	    ],
        ]); ?>
 	    </div>
     </div>
   </div>
</div>

I only want to save the dropdwonlist into the database. I have a Dropdownlist and a Gridview. The Gridview is generated using QueryBuilder and it has a Parameter. I want it that when the Dropdownlist is onChange, it will determine what will be displayed on the Gridview. The Parameter, $groupingId from the searchModel of the Gridview must be equal to the grouping_id of the Dropdownlist.

dropdownGroup

How do I achieve this in making the gridview dependent on the dropdownlist using the $groupingId parameter?


(Alirz23) #2

there is a wiki article but its for yii1 you just have to convert it to yii2

https://www.yiiframework.com/wiki/648/update-gridview-with-dropdown-selection

there is also a video


(Folumikeidowu) #3

The Challenge is that, if you look at my Controller,

    public function actionCreate()
{
    $model = new Exam();
$searchModel = new SubjectSearch();
$dataProvider = $searchModel->searchSubject(Yii::$app->request->queryParams);

if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
    	\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    	return ActiveForm::validate($model);
   	}
if ($model->load(Yii::$app->request->post())) {
	
		$model->attributes = $_POST['Exam'];
		$model->save();
		return $this->redirect(['index']);
   	}
    else {
        return $this->render('create', [
            'model' => $model,
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider,
        ]);
    }
}

I want to save the content of the dropdownlist into:

 $model = new Exam();

and not:

$searchModel = new SubjectSearch();

Which is another table. Thats why I made my Dropdownlist to have $model of the Exam model class as shown below.

        <div class="col-xs-12 col-sm-4 col-lg-4">    
      <?= $form->field($model, 'exam_group_id')->widget(Select2::classname(), [
            'data' => ArrayHelper::map(app\models\Grouping::find()->all(),'grouping_id','grouping_name'),
            'language' => 'en',
            'options' => ['placeholder' => '--- Select Grouping ---'],
            'pluginOptions' => [
                'allowClear' => true
            ],
        ]); ?> 
    </div>

(Softark) #4

It will be a bit complex solution, although your needs looks very simple at the first glance. So I can not give you a full solution, but only a general hint.

  1. You’d be better use 2 forms: One is for Exam model which you already have in the view. This is for saving Exam model. An the other is for SubjectSearch model that submits the query parameter for the grid. You are currently using a separated parameter of groupingId, but I think you can add it as an attribute to the SubjectSearch model to make things simple.
  2. You can include a form for SubjectSearch in the view script, just as _search sub view is included in index view in Gii-generated CRUD. And the form for search should use GET method, not POST. As you can see, _search form uses GET, not POST.
  3. Just as the gridview is updated by the _search form submission in index action of the Gii-generated CRUD, you should be able to update your grid with your form for SubjectSearch.
  4. The form for SubjectSearch should be invisible to the users. In order to do so, you can omit the submit button from it, and you should include just one hidden field of groupingId in it.
  5. In order to make the form work, you have to write some javascript. Add an event handler for the dropdownList’s onChange event in which you should copy the value of the dropdownList to the hidden field and submit the search form.
  6. The controller code should be able to handle the GET request submitted by the search form, while it should also be able to handle the POST request submitted by the form for Exam. At this point, I have no clear idea about what you should write for it.

I hope it will be a little help for you.


(Folumikeidowu) #5

Who can help me out. Am new to Yii2, but I need to resolve this problem


(Softark) #6

So, what’s bothering you? What do you think is difficult for you to understand?


(Folumikeidowu) #7

I need a sample of how to go about it


(Softark) #8

searchSubject() method doesn’t need $params since you are not making use of it. So it will go like this:

    public function searchSubject($groupingId = null)
    {
        $query = (new \yii\db\Query())
            ->select(['sbt.subject_id', 'sbt.subject_title', 'grp.grouping_id', 'grp.grouping_name', 'sgp.subject_grouping_id'])
            ->from('grouping grp')
            ->join('INNER JOIN', 'subject_grouping sgp', 'sgp.subject_grouping_grouping_id = grp.grouping_id')
            ->join('INNER JOIN', 'subject sbt', 'sbt.subject_id = sgp.subject_grouping_subject_id')
            ->where([
                'sbt.is_status' => '0',
                'grp.grouping_id' => $groupingId
            ])->orderBy('subject_title ASC');
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);
        return $dataProvider;
    }

And the controller action will be like this:

    public function actionCreate($groupId = null)
    {
        $model = new Exam();
        if ($model->load(Yii::$app->request->post())) {
            if (Yii::$app->request->isAjax ) {
                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
                return ActiveForm::validate($model);
            } else {
                if ($model->save()) {
                    return $this->redirect(['index']);
                }
            }
        }
        $searchModel = new SubjectSearch();
        $dataProvider = $searchModel->searchSubject($groupIId);
        if (Yii::$app->request->isPjax) {
            return $this->renderPartial('create', [
                'model' => $model,
                'dataProvider' => $dataProvider,
            ]);
        } else {
            return $this->render('create', [
                'model' => $model,
                'dataProvider' => $dataProvider,
            ]);
        }
    }

The first half of the method deals with the $model and the POST request. It also handles the ajax validation.
And the second half renders the form and the grid. If it is a Pjax request, it tries to render just the grid.

Now the view script goes like this:

    <?= $form->field($model, 'exam_group_id')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(app\models\Grouping::find()->all(), 'grouping_id', 'grouping_name'),
        'language' => 'en',
        'options' => [
            'placeholder' => '--- Select Grouping ---',
            'id' => 'group-input',
        ],
        'pluginOptions' => [
            'allowClear' => true
        ],
    ]); ?>

There’s nothing special for the form for $model, but you have to set id attribute for the input in order to refer to it in javascript later.

The view also has a grid and a form for it.

<?= Html::beginForm(['create'], 'get', ['id' => 'grid-search-form']) ?>
<?= Html::hiddenInput('groupId', null, ['id' => 'group_id']) ?>
<?= Html::endForm() ?>

<?php
Pjax::begin([
    'formSelector' => '#grid-search-form',
]);
echo GridView::widget([
    'dataProvider' => $dataProvider,
    'summary' => '',
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],
        'subject_title',
    ],
]);
Pjax::end();
?>

The form should use GET method, just as _search form of Gii generated index page does. The form has no visible field nor submit button. It should be used later by javascript.
And the grid should be enclosed in Pjax widget, whose formSelector should be the above mentioned form.

And the javascript.

$('#group-input').onChange(function(event){
    $('#group_id').val($('#group-input').val());
    $('#grid-search-form').submit();
    event.preventDefault();
});

It should catch the change event of the select2 widget and copy its value to the search form and submit it.

That’s all.

Well, please note the following:

I don’t know if it will work or not. It’s not a sample that you want. It’s just a kind of scratch that I would start with. If it were my job to accomplish, I would test it and manage to make it work. But I will not do it, because it’s not my job. It’s yours, my friend.

Please don’t respond me with a single sentence of ‘It doesn’t work’.


(Folumikeidowu) #9

Thanks. Its resolved