Yii2 Gridiview filter not working properly. Selecting one filter have impact on other filters. Changing one filter (dropdown) auto-select the values of other filters (dropdowns). This problem also exists in URL as well, changing one filter appends the other filters in URL as well and result shown as combined. but in reality only one filter should be applied which is being changed.
// Search Model, adding dummy table names
public function search($params)
{
$query = Model::find()->with('model_b');
if (empty($params['sort'])) {
$query->orderBy("group, " . Model::getSortByType() . ', "title"');
}
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'attributes' => [
'code',
'title',
'updated_at'
]
]
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'type' => $this->type,
'price_type' => $this->price_type,
'status' => $this->status,
'terms_related' => $this->terms_related,
'required' => $this->required,
'group' => $this->group,
]);
$query->andFilterWhere(['ilike', 'title', $this->title]);
$query->andFilterWhere(['is_qr' => $this->is_qr]);
return $dataProvider;
}
//Controller
public function actionIndex()
{
$searchModel = new ModelSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render("index", [
"searchModel" => $searchModel,
"dataProvider" => $dataProvider,
]);
}
// In View, the filter I change
[
'attribute' => 'is_qr',
'format' => 'boolean',
'filter' => [1 => 'TRUE', 0 => 'FALSE'],
'content' => function ($service) { return ((int) $service->is_qr === 1) ? 'TRUE' : 'FALSE'; }
],
// the filter being changed with above filter
[
'attribute' => 'terms_related',
'filter' => array(0 => 'FALSE', 1 => 'TRUE'),
'content' => function ($service) { return ((int) $service->terms_related === 1) ? 'TRUE' : 'FALSE'; }
]
Observations: Consider I have 5 filters in a GridView.
Action 1: I changed a filter, only that filter is applied first time but after page reload, other filters are being populated with values with "0". Because on selecting one filter, all filters are being pushed in URL with empty values other than selected one. And filters with empty values are being applied to rest of the filters with "0" value
Problem The problem is, once I select a filter, gridview sends all possible filters in URL. The filters I did not select, have empty values.
Yii::$app->request->queryParams
This has all filters and the filters other than I selected have empty values, and
$this->load($params);
in search()
deals empty values as 0. So, filters that I have not touched are being populated with "0" value.
I have found the solution, it is a custom solution but works for me. I created a Trait
trait ParamsTrimable
{
public function trimParams($params, $modelClass)
{
$modelClass = basename(str_replace('\\', '/', $modelClass));
if ($params[$modelClass]) {
$params[$modelClass] = array_filter($params[$modelClass], function ($value) {
return ($value !== '');
});
}
return $params;
}
}
And before
$this->load($params);
I called trait's function i.e.
$params = $this->trimParams($params, static::class);
$this->load($params);
Reason behind the trait solution is, this problem may occur in other listings as well. To fix, we only need to use
trait and call the function to remove empty values from params.