Yii2: GridView Multiple filter

Created on 24 Jul 2014  路  12Comments  路  Source: yiisoft/yii2

Hi, I have done for my self project multi choice of filters, for this I had to change the following files:
yii.gridView.js

applyFilter: function () {
            var $grid = $(this);
            var settings = gridData[$grid.prop('id')].settings;
            var data = {};
            $.each($(settings.filterSelector).serializeArray(), function () {
                if (data[this.name] === undefined) {
                    data[this.name] = this.name.indexOf('[]') === -1 ? this.value : [this.value];
                } else if (typeof data[this.name] === 'object') {
                    data[this.name].push(this.value);
                }
            });

            $.each(yii.getQueryParams(settings.filterUrl), function (name, value) {
                if (data[name] === undefined && (typeof value === 'object' && value.length > 1)) {
                    data[name] = value;
                }
            });

            var pos = settings.filterUrl.indexOf('?');
            var url = pos < 0 ? settings.filterUrl : settings.filterUrl.substring(0, pos);

            $grid.find('form.gridview-filter-form').remove();
            var $form = $('<form action="' + url + '" method="get" class="gridview-filter-form" style="display:none" data-pjax></form>').appendTo($grid);
            $.each(data, function (name, value) {
                if (typeof value === 'object') {
                    $.each(value, function (id, value_multi) {
                        $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value_multi));
                    });
                } else {
                    $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value));
                }
            });
            $form.submit();
        },

&&
yii.js

getQueryParams: function (url) {
            var pos = url.indexOf('?');
            if (pos < 0) {
                return {};
            }
            var qs = url.substring(pos + 1).split('&');
            for (var i = 0, result = {}; i < qs.length; i++) {
                qs[i] = qs[i].split('=');
                if (result[decodeURIComponent(qs[i][0])] === undefined) {
                    result[decodeURIComponent(qs[i][0])] = decodeURIComponent(qs[i][0]).indexOf('[]') === -1 ? decodeURIComponent(qs[i][1]) : [decodeURIComponent(qs[i][1])];
                } else if (typeof result[decodeURIComponent(qs[i][0])] == 'object') {
                    result[decodeURIComponent(qs[i][0])].push(decodeURIComponent(qs[i][1]));
                }
            }
            return result;
        },

Please, check, maybe can be useful

bug

Most helpful comment

@pptyasar Your luck, I鈥檝e found the solution in one of my projects. Look, I created my own yii.gridView.js file and changed the config:

        'components' => [
                'assetManager' => [
                        'bundles' => [
                                'yii\grid\GridViewAsset' => [
                                        'sourcePath' => __DIR__ . '/../assets',
                                ],
                        ],
                ],
        ],

In yii.gridView.js I replaced the applyFilter function:

        applyFilter: function () {
            var $grid = $(this), event;
            var settings = gridData[$grid.attr('id')].settings;
            var data = {};
            $.each($(settings.filterSelector).serializeArray(), function () {
                if (data[this.name] === undefined) {
                    data[this.name] = this.name.indexOf('[]') === -1 ? this.value : [this.value];
                } else if (typeof data[this.name] === 'object') {
                    data[this.name].push(this.value);
                }
            });

            $.each(yii.getQueryParams(settings.filterUrl), function (name, value) {
                if (data[name] === undefined) {
                    data[name] = value;
                }
            });

            var pos = settings.filterUrl.indexOf('?');
            var url = pos < 0 ? settings.filterUrl : settings.filterUrl.substring(0, pos);

            $grid.find('form.gridview-filter-form').remove();
            var $form = $('<form action="' + url + '" method="get" class="gridview-filter-form" style="display:none" data-pjax></form>').appendTo($grid);
            $.each(data, function (name, value) {
                if (typeof value === 'object') {
                    $.each(value, function (id, value_multi) {
                        $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value_multi));
                    });
                } else {
                    $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value));
                }
            });

            event = $.Event(gridEvents.beforeFilter);
            $grid.trigger(event);
            if (event.result === false) {
                return;
            }

            $form.submit();

            $grid.trigger(gridEvents.afterFilter);
        },

But keep in mind that this code is forked from the summer 2015 version, so it could lack some features.

All 12 comments

This might not work when the url params are done trough path?

Yea, multiple dont worked when start change action
here

here1

and here

here2

I've also faced a problem of using multiple selection in filter.
At least select2 is not working.

I've also found related thread on stack overflow: http://stackoverflow.com/questions/30780797/yii2-grid-multi-select-filter-not-working

So, I think it can be considered as a bug.

Same problem. All values of a multiple select are overwritten by the last value here:

            $.each($(settings.filterSelector).serializeArray(), function () {
                data[this.name] = this.value;
            });

https://github.com/yiisoft/yii2/blob/95ba06c01b35b84740cd566edf4bdc0611db1efa/framework/assets/yii.gridView.js#L88

@egoroof show us your GridView definition and your ModelSearch::search method please

@Faryshta wat? Are you right about username mention? :rabbit:

@WaterSpout can you show us your GridView and your search method?

@egoroof sorry my bad

Sorry, not seen comment. I edited yii.gridView.js and yii.js.
its grid

$grid = GridView::widget([
            'dataProvider'=> $dataProvider,
            'filterModel' => $searchModel,
            'columns' => $columns_grid,
            'responsive'=>true,
            'hover'=>true,
            'exportConfig' => [
                GridView::EXCEL => ['label' => 'Excel'],
            ],
            'export'=>false,
            'panel' => [
                'heading'=>'<h3 class="panel-title">袣芯屑锌邪薪懈懈</h3>',
                'type'=>'success',
                'before'=>$before,
                'after'=> '</form>',
                'showFooter'=>false
            ],
        ]);

its $columns_grid example

[
                'attribute'=>'industrypage',
                'width' => '400px',
                'filter' => Html::dropDownList('industrypage[]', Yii::$app->request->get('industrypage'), Company::$industry_mess, ['class'=>'select2', 'multiple'=>'multiple']),
                'value' => function ($model) {
                    return Company::$industry_mess[$model->industrypage];
                },
            ],

Or

[
                'attribute'=>'last_profession',
                'filterType'=>GridView::FILTER_SELECT2,
                'filter'=>ArrayHelper::map(Responses::find()->orderBy('last_profession')->asArray()->all(), 'last_profession', 'last_profession'),
                'filterWidgetOptions'=>[
                    'pluginOptions'=>['allowClear'=>true],
                    'options'=>['multiple'=>true],
                ],
                'filterInputOptions'=>['placeholder'=>'袥褞斜芯泄']
            ],

$searchModel example



    public function search($params)
    {
        $query = Responses::find();
        if (isset($params['ResponsesSearch']) && isset($params['ResponsesSearch']['last_profession']) && is_array($params['ResponsesSearch']['last_profession'])) {
            $params['ResponsesSearch']['last_profession'] = implode(",", $params['ResponsesSearch']['last_profession']);
        }

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => !isset($page_size) ? false : ['pageSize' => $page_size],
            'sort'=> ['defaultOrder' => ['date_published'=>SORT_DESC]]
        ]);

        // load the seach form data and validate
        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }
        if (!empty($this->last_profession)) {
            $this->last_profession = explode(',', $this->last_profession);
            $val_last = "'".implode("','", $this->last_profession)."'";
            $query->andWhere("`last_profession` IN($val_last)");
        }

        return $dataProvider;
    }

how to fix @baibaratsky

@pptyasar Sorry, I can鈥榯 recall it. It was two years ago.

@pptyasar Your luck, I鈥檝e found the solution in one of my projects. Look, I created my own yii.gridView.js file and changed the config:

        'components' => [
                'assetManager' => [
                        'bundles' => [
                                'yii\grid\GridViewAsset' => [
                                        'sourcePath' => __DIR__ . '/../assets',
                                ],
                        ],
                ],
        ],

In yii.gridView.js I replaced the applyFilter function:

        applyFilter: function () {
            var $grid = $(this), event;
            var settings = gridData[$grid.attr('id')].settings;
            var data = {};
            $.each($(settings.filterSelector).serializeArray(), function () {
                if (data[this.name] === undefined) {
                    data[this.name] = this.name.indexOf('[]') === -1 ? this.value : [this.value];
                } else if (typeof data[this.name] === 'object') {
                    data[this.name].push(this.value);
                }
            });

            $.each(yii.getQueryParams(settings.filterUrl), function (name, value) {
                if (data[name] === undefined) {
                    data[name] = value;
                }
            });

            var pos = settings.filterUrl.indexOf('?');
            var url = pos < 0 ? settings.filterUrl : settings.filterUrl.substring(0, pos);

            $grid.find('form.gridview-filter-form').remove();
            var $form = $('<form action="' + url + '" method="get" class="gridview-filter-form" style="display:none" data-pjax></form>').appendTo($grid);
            $.each(data, function (name, value) {
                if (typeof value === 'object') {
                    $.each(value, function (id, value_multi) {
                        $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value_multi));
                    });
                } else {
                    $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value));
                }
            });

            event = $.Event(gridEvents.beforeFilter);
            $grid.trigger(event);
            if (event.result === false) {
                return;
            }

            $form.submit();

            $grid.trigger(gridEvents.afterFilter);
        },

But keep in mind that this code is forked from the summer 2015 version, so it could lack some features.

Was this page helpful?
0 / 5 - 0 ratings