Post data from gridview widget

I’am a beginner with Yii2 and found my-self in trouble with simple task: how to retrieve table data via POST request?

My code:

    <?=Html::beginForm(['list-profile/index'], 'get', ['data-pjax' => '', 'class' => 'form-inline', 'id' => 'list-channels-groups']);?>
            <?=Html::DropDownList('name', $getChannelGroups[0]->name,
                ArrayHelper::map(\app\models\ListChannelsGroups::find()->asArray()->all(), 'id', 'name'), ['class' => 'form-control', 'prompt' => Yii::t('app', '--Choose channel list group--'), 'onchange'=>'this.form.submit()'])
            ?>
            <?php if (Yii::$app->request->get('name')) : ?>
            <span class="pull-right">
                <?=Html::a(Yii::t('app', 'Add all channels'), ['addall', 'name' => Yii::$app->request->get('name')], ['class' => 'btn btn-success'])?>
                <?=Html::a(Yii::t('app', 'Remove all channels'), ['delall', 'name' => Yii::$app->request->get('name')], ['class' => 'btn btn-danger'])?>
                <?=Html::a(Yii::t('app', 'Resort channels'), ['resort', 'name' => Yii::$app->request->get('name')], ['class' => 'btn btn-warning'])?>
            </span>
            <?=Html::endForm();?>
            <?php endif; ?>
            <!-- Select profile list group END -->

            <br>
            <?=GridView::widget([
                'id' => 'list-channels',
                'dataProvider' => $dataProvider,
                'filterModel' => $searchModel,
                'rowOptions' => function ($model) {
                    if (strtotime($model->date_start) > strtotime("now")) {
                        return ['class' => 'info'];
                    } else if ($model->date_end == null) {
                        return ['class' => 'success'];
                    } else if (strtotime($model->date_end) < strtotime("now")) {
                        return ['class' => 'warning'];
                    }
                },
                'pager' => [
                    'firstPageLabel' => Yii::t('app', 'First'),
                    'lastPageLabel' => Yii::t('app', 'Last'),
                ],
                'columns' => [
                    [
                        'label'=>'#',
                        'attribute' => 'channel.sort',
                        'value' => 'channel.sort',
                    ],
                    [
                        'label'=>'Sort No.',
                        'attribute'=>'no',
                        'format' => 'raw',
                        'value'=> function ($data) {
                            return Html::textInput("sortOrder$data->no",$data->no,array("style"=>"width:40px;"));
                        },
                    ],
                    [
                        'attribute' => 'channel.name',
                        'format' => 'raw',
                        'value' => function ($data) {
                            return Html::a($data->getChannelName($data->channel_id), ['update', 'id' => $data->id, 'name' => Yii::$app->request->get('name')], ['data-pjax' => 0]);
                        },
                    ],
                     'create_time',
                     'update_time',
                    ['class' => 'yii\grid\ActionColumn',
                        'template' => '{remove}',
                        'buttons' => [
                            'remove' => function ($url, $model, $key) {
                                return Html::a('<span class="glyphicon glyphicon-remove text-danger"></span>', ['list-profile/index', 'rem_id' => $model->id, 'name' => Yii::$app->request->get('name')], ['title' => Yii::t('app', 'Remove from profile'),
                                 ]
                                );
                            }
                        ],
                        'contentOptions' => ['style' => 'min-width: 50px;text-align: center;'],
                    ]
                ],
            ]);?>
        </div>
    <?php endif; ?>
    <?php Pjax::end(); ?>

At the top of code snippet you see buttons, one of them is “Resort channels”. How to do, that when I press that button, all data from table be POSTed into my controller for further operations? This looks like very simple task in plain PHP (wrap in form with hidden inputs), but with Yii2 this is insanely complex and I simply stuck.

1 Like

Do you want to post whole contents of GridView?

1 Like

No, just a “Sort No.” column.

Aha. Then:

  1. You need to wrap the grid with the form that contains submit button.
  2. You need a column with checkboxes or, alternatively, hidden inputs.

PJAX would probably make it harder to implement. Make it work without PJAX first.

here is the example
gridview column using checkbox

[
                        'class' => 'yii\grid\CheckboxColumn',
                        'checkboxOptions' =>
                            function($model) {
                                return ['value' => $model->id, 'class' => 'checkbox-row', 'id' => 'checkbox'];
                            }
                    ],

you can require the value from the controller like this below
$selection = Yii::$app->request->post()['selection'];

Guys, does this really helps to pass data from textbox? Here is a visual of how table looks now https://imgur.com/fh7dSzd . If I wrape up it in form element textbox input will be passed to POST? Thank you for your time and help.

Yes, all the inputs wrapped with a form will be submitted.

Alright, My code now looks like:

<?=Html::beginForm(['list-profile/resort'], 'post', ['class' => 'form-inline', 'id' => 'resort-channel-list']);?>
            <?=Html::a(Yii::t('app', 'Resort channels'), ['resort', 'name' => Yii::$app->request->get('name')], ['class' => 'btn btn-warning'])?>
            <?=GridView::widget([
                'dataProvider' => $dataProvider,
                'filterModel' => $searchModel,
                'rowOptions' => function ($model) {
                    if (strtotime($model->date_start) > strtotime("now")) {
                        return ['class' => 'info'];
                    } else if ($model->date_end == null) {
                        return ['class' => 'success'];
                    } else if (strtotime($model->date_end) < strtotime("now")) {
                        return ['class' => 'warning'];
                    }
                },
                'pager' => [
                    'firstPageLabel' => Yii::t('app', 'First'),
                    'lastPageLabel' => Yii::t('app', 'Last'),
                ],

                'columns' => [
                    [
                        'class' => 'yii\grid\CheckboxColumn',
                        'checkboxOptions' =>
                            function($model) {
                                return ['value' => $model->id, 'class' => 'checkbox-row', 'id' => 'checkbox'];
                            }
                    ],
                    [
                        'label'=>'#',
                        'attribute' => 'channel.sort',
                        'value' => 'channel.sort',
                    ],
                    [
                        'label'=>'Sort No.',
                        'attribute'=>'no',
                        'format' => 'raw',
                        'value'=> function ($data) {
                            return Html::textInput("sortOrder$data->no",$data->no,array("style"=>"width:40px;"));
                        },
                    ],
                    [
                        'attribute' => 'channel.name',
                        'format' => 'raw',
                        'value' => function ($data) {
                            return Html::a($data->getChannelName($data->channel_id), ['update', 'id' => $data->id, 'name' => Yii::$app->request->get('name')], ['data-pjax' => 0]);
                        },
                    ],
                     'create_time',
                     'update_time',
                    ['class' => 'yii\grid\ActionColumn',
                        'template' => '{remove}',
                        'buttons' => [
                            'remove' => function ($url, $model, $key) {
                                return Html::a('<span class="glyphicon glyphicon-remove text-danger"></span>', ['list-profile/index', 'rem_id' => $model->id, 'name' => Yii::$app->request->get('name')], ['title' => Yii::t('app', 'Remove from profile'),
                                 ]
                                );
                            }
                        ],
                        'contentOptions' => ['style' => 'min-width: 50px;text-align: center;'],
                    ],
                ]
            ]);?>
        </div>
        <?=Html::endForm();?>

But when I try to catch POST in my controller it just gives me:

Array 
(
)

No PJAX.

Do you have any checkboxes checked?

Yes, all checkboxes are selected. Controller:

// Resort channels from list
    public function actionResort()
    {
        echo '<pre>';
        print_r(Yii::$app->request->post());
        echo '</pre>';
    }

you should try using ActiveForm instead of beginForm.

You need to use a submit button in the form instead of a link button.

1 Like

Yes! It works when I put button instead of link. What a silly me :slight_smile: thank you!

Ha, now I have slightly more complicated problem :slight_smile: on the same matter.

I need to submit data on text input field in the table. Sounds unclear, I know. Let me explain:

I have table like this

There is a column “Sort No”. My task is to submit ‘sort no’ value as soon as user enters data on it AND increment other fields which are more than the value submitted (to avoid duplicates).

When I submit data with button, whole table goes to POST and I can’t increment values properly.

My controller for this task:

// Resort channels from list
public function actionResort()
{
    $request = Yii::$app->request->post();

    if (!empty($request)) {

        // find dupes and increment by 1
        $session = Yii::$app->session;

        // profile_id
        if ($session->has('profile')) {
            $profile_id = $session->get('profile');
        } else {
            $profile_id = Yii::$app->user->identity->profile_id;
        }

        // list_id
        if ($session->has('list_id')) {
            $list_id = $session->get('list_id');
        } else {
            $list_id = null;
        }

        // change channel sorting no
        foreach ($request['chanId'] as $channelId) {
            $resort_position = $request["$channelId"];
            $chan = ListProfile::findOne(['id' => $channelId]);
            $chan->no = $resort_position;
            $chan->save();

            if ($chan->save()) {
                $other_chans = ListProfile::find()
                    ->where(['profile_id' => $profile_id])
                    ->andWhere(['list_id' => $list_id])
                    ->andWhere(['>=', 'no', $chan->no])
                    //->andWhere(['!=','id', $channelId])
                    ->all();
            }
        }

            if ($other_chans) {
                foreach ($other_chans as $oc) {
                    $oc->no = $oc->no + 1;
                    $oc->save();
                }
            }
    }

    return $this->redirect(['index', 'name' => $request['resort']]);
}

Of course this code isn’t working, but you will get idea how I think my task should be solved.

As I see no reply :slight_smile: yea, Yii2 is not a candy indeed. Here is simple question:

how to send data via POST of single row in table? Because if I wrap whole table in form submit button send whole table data via POST.

There’s no such functionality out of the box. You can either collect data via JavaScript and use XMLHttpRequest (jQuery AJAX) to send it or change rendering somehow so rows are wrapped into form tags.

Is there any examples with Yii2 and such data collection with AJAX? Maybe I can do something with pjax?

There should be but I don’t have any.