To implement this feature we only need to make a change to the model's search class and add a dropdown control to it's index view.

Search Model

To dynamically change the number of records displayed on a page we first need to add a page size property to the search class:

class UserSearch extends UserRecord
{
    // Additional search attributes
    public $_page_size = 20;

Next, we need to add this attribute to our rules() method:

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [
                [
                    'id',
                    ....
                ],
                'integer'
            ],
            [
                [
                    'username',
                    'name',

                    ...
                    ...

                    '_page_size',
                ],
                'safe'
            ],
        ];
    }

Finally, we need to set the pagination property for our data provider object (line 18)

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = UserRecord::find();

        // Load search parameters
        $this->load($params);

        // Set query and pagination
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => ['pageSize' => $this->_page_size],
        ]);

        // Set data provide sort
        $dataProvider->setSort([
            'defaultOrder' => ['username' => SORT_ASC],
            'attributes' => [
                'username',
                'name',
                ...
            ]
        ]);

        // If search attributes are invalid return no records.
        if (!$this->validate())
        {
            $query->where('0=1');
            return $dataProvider;
        }

        // Set search criteria....

Index View

Now we can add a pagination control to our view (in this case a dropdown list):


    <?php
    // prefix for page size control's 'id' and 'name'
    $form_name = $searchModel->formName();
    ?>
    <div class="row">
        <div class="grid-page-size" style="margin-bottom: 40px; width: 250px;">
            <div class="col-sm-6">
                <?= Html::label('Page size: ', $form_name . '[_page_size]', ['style' => 'margin-top: 4px;'])?>
            </div>
            <div class="col-sm-6">
                <?= Html::dropDownList(
                    $form_name . '[_page_size]',
                    $searchModel->_page_size,
                    [
                        20 => '20',
                        50 => '50',
                        100 => '100',
                        250 => '250',
                        500 => '500',
                        0 => 'Unlimited',
                    ],
                    [
                        'class' => 'form-control',
                        'id' => strtolower($form_name) . '-_page_size',
                    ])
                ?>
            </div>
        </div>
    </div>

Finally, in our view we update our GridView to listen out for changes to our page size dropdown. So here, we assigned the id of our HTML element to the filterSelector property.


    <?= kartik\grid\GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'filterSelector' => '#'.strtolower($form_name) . '-_page_size',
        'columns' => $gridColumns,
        'pjax' => true,
        'pjaxSettings' => [
            'options' => ['id' => $pjaxContainer],
        ],
    ]);

Note, the above example is using kartik\grid\GridView