Search code examples
phpgridviewyii2

Yii2 GridView Filters behaving not working properly


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.


Solution

  • 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.