How to sort model relation in GridView?

Salut, everyone!

Could you help me with my problem.

I have database structure like this:

Item

  • name

  • description

Complectation

  • item_id

  • width

  • attribute

  • etc…

Item has many Complectations.

Complectation has one Item.

Complectation has attribute named width.

I’ve made GridView with columns in Yii 2.0:

Name: item->name

Description: item->description

Min width: complectation -> width -> here I select MIN width of item complectation

Max width: complectation -> width -> here I select MAX width of item complectation

And now my problem begin.

I wanna make sorting option for ‘Min/Max width’ column, but really I can’t gain this…

Could you suggest me documentation or advice about my issue?

Hi,

Several things should be checked, tried like this:




[

         	'attribute' => 'width',

         	'label' => 'Min width',

         	'enableSorting' => true,

]

Post your Grifview here

misterlexa123, read it: http://www.yiiframework.com/wiki/653/displaying-sorting-and-filtering-model-relations-on-a-gridview/

Pay attention to this section of code:


    // Important: here is how we set up the sorting

    // The key is the attribute name on our "TourSearch" instance

    $dataProvider->sort->attributes['city'] = [

        // The tables are the ones our relation are configured to

        // in my case they are prefixed with "tbl_"

        'asc' => ['tbl_city.name' => SORT_ASC],

        'desc' => ['tbl_city.name' => SORT_DESC],

    ];

    // Lets do the same with country now

    $dataProvider->sort->attributes['country'] = [

        'asc' => ['tbl_country.name' => SORT_ASC],

        'desc' => ['tbl_country.name' => SORT_DESC],

    ];

Hi, guys! Thank you for your replies!

Really, I been confused with my issue for 2 last days and I’ve found the solution.

I am happy!

I read amazing article "Filtering and sorting by calculated/related fields in Yii 2.0"; You can google it.

Now my code looks like this and this is perfectly works:

Model

  1. I added to the rules() construction [[‘minWidth’], ‘safe’]

  2. I made getter for minimal width of model getMinWidth()


class Model extends \yii\db\ActiveRecord


    /**

     * @inheritdoc

     */

    public static function tableName()

    {

        return 'model';

    }


    /**

     * @inheritdoc

     */

    public function rules()

    {

        return [

            [['description', 'is_popular'], 'string'],

            [['min_width', 'max_width'], 'integer'],

            [['min_price', 'max_price'], 'number'],

            [['name'], 'string', 'max' => 45],

            [['promo'], 'string', 'max' => 255],

            [['img', 'small_img'], 'string', 'max' => 255],

            [['minWidth'], 'safe']

        ];

    }


    /**

     * @inheritdoc

     */

    public function attributeLabels()

    {

        return [

            'id' => Yii::t('app', 'ID'),

            'name' => Yii::t('app', 'Name'),

            'promo' => Yii::t('app', 'Promo'),

            'description' => Yii::t('app', 'Description'),

            'img' => Yii::t('app', 'Image'),

            'small_img' => Yii::t('app', 'Small image'),

            'is_popular' => Yii::t('app', 'Is Popular'),

            'minWidth' => Yii::t('app', 'Min width'),

        ];

    }


    /**

     * @return \yii\db\ActiveQuery

     */

    public function getComplectations()

    {

        return $this->hasMany(Complectation::className(), ['model_id' => 'id']);

    }

    

    /**

     * @return minimal width of model's complectation

     */

    public function getMinWidth()

    {

        $complectations = $this->complectations;

        yii\helpers\BaseArrayHelper::multisort($complectations,'width',SORT_ASC);

        return $complectations[0]->width;

    }


    /**

     * @return \yii\db\ActiveQuery

     */

    public function getImages()

    {

        return $this->hasMany(Image::className(), ['model_id' => 'id']);

    }


}

Controller

When user requests actionIndex, he will receive the gridview with sorting option.

As you told me, I added this construction:


        $dataProvider->setSort([

            'attributes' => [

                'id',

                'name',

                'minWidth'=>[

                    'asc' => ['complectation.width' => SORT_ASC],

                    'desc' => ['complectation.width' => SORT_DESC],

                ],

            ]

        ]);

Then I added join: $query->joinWith([‘complectations’]);

I get this


    public function actionIndex()

    {

        $query = Model::find();

        

        //get data for gridView

        $dataProvider = new ActiveDataProvider([

            'query' => $query,

        ]);


        $dataProvider->setSort([

            'attributes' => [

                'id',

                'name',

                'minWidth'=>[

                    'asc' => ['complectation.width' => SORT_ASC],

                    'desc' => ['complectation.width' => SORT_DESC],

                ],

            ]

        ]);

        

        $query->joinWith(['complectations']);


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

            'dataProvider' => $dataProvider,

        ]);

    }

My view


    <?=GridView::widget([

        'dataProvider' => $dataProvider,

        'tableOptions' => ['class' => 'table'],

        'layout' => '{items}',

        'options' => ['class' => 'items-list'],

        'columns' => [

            'id',

            'name',

            'minWidth',

            ['class' => 'yii\grid\ActionColumn'],

        ],

    ]);?>