Get data filtered of GridView in controller

Hello. I wanna to export the data already filtered in the gridview. Can I send the dataProvider of the gridview to the controller and get the data in the action? How?

Thanks

You have this backwards :grinning:
The controller is there the data originated from - if you notice the $dataProvider is passed from the controller action to the view. I assume you want to create an CSV/PDF file for your users to download (in the view) - so you will have to create a new action for PDF download that will call the controller action to produce. I just made an assumption this is a PDF - if it is you may want to look at GitHub - kartik-v/yii2-mpdf: A Yii2 wrapper component for the mPDF library which generates PDF files from UTF-8 encoded HTML.

Hello @snathan … thanks for your answer!!!
Yes, I wanna export the data from the gridview but with the filters applied by the user in the index page (column filters, advanced search, etc.).
Because of that, my idea is to send back to the controller the dataProvider (with the filters included), get the models, iterate and export the data.
I need special considerations in the export then I don’t wanna use any widget.

I understand the requirement now. When the filter are invoked, a call is made back to the server with the filters - if you look at the URL you will notice the search parameters being sent. With that I assume you may be able to trap what filters were requested. I have not done this before, but it should be viable option. When you get the records back, also send the filter/search options back embedded in the “export rows” URL. Then when the user clicks on it, you can resubmit the chosen filters - is at least what I am thinking as an option. Other options may be to save the filters in a session.

Now, I’m getting the approach to save the filters in session (in the index action), but why don’t send the dataProvider from view to controller? If I can do that the solution would be very simple.

Did you built dataProvider in view?

Hello @InsaneSkull and Thanks. I generate the dataProvider in the actionIndex (controller) as allways:

 $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  ...
 return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
 ]);

I send the dataProvider (with the filters applied by the user) to the controller, when the user clicks a link:

Html::a('<i class="fas fa-money-check-alt mr-2"></i>'.Yii::t('app', 'Checks'),
                           ['export-checks'],
                           ['class' => 'btn btn-warning', 'data-pjax' => '0', 'data' => [
                                'method' => 'POST',
                                'params' => ['dataProvider' => $dataProvider]
                           ]
])

The only part that I can’t figure out is the actionExportChecks (controller). How I can “convert” the parameter ‘dataProvider’ in a object dataProvider.

$dataProvider = Yii::$app->request->post('dataProvider', null);

Thanks

1 Like

You just need to hint the controller to export the dataProvider by passing the flag. There is no need of separate action unless you are passing extra form fields.

You can do something like below if you are using simple export.

View

Html::a('<i class="fas fa-money-check-alt mr-2"></i>'.Yii::t('app', 'Checks'),
     Url::current(['export' => 1]),
     ['class' => 'btn btn-warning', 'data-pjax' => '0']
)

Controller

$dataProvider = $searchModel->search(Yii::$app->request->queryParams);

// Do all the filtering related to dataProvider above this block
if (Yii::$app->request->get('export')) {
      // Export Code and return the file         
}

 return $this->render('index', [
    'searchModel' => $searchModel,
    'dataProvider' => $dataProvider,
 ]);

You will retain all the filter and filtered dataProvider as well.

Yes, this is a good idea @InsaneSkull … I’m sure it works, but it will be interesting to separate the “index” logic with the “export” logic … I don’t understand yet why I can use the dataProvider sended by the view.
Sorry for my insistence :blush:

You break the MVC framework approach by doing that. Besides I am not sure how exactly you would pass the the dataProvider back to controller. You can only call URLs with parameters and I would be curious to know how one can achieve that.

Here is another option for you: Enclose the search portion of the view into a submittable form. When the form button (which will be your export button) is clicked, you can submit the search filter parameters back to a new controller action to produce the export.

As I think about this more, you should follow the approach by @InsaneSkull - can’t think of a cleaner / better or appropriate option. He already has the code written for you!

Thanks @snathan and @InsaneSkull

One thing that you refuse to unlearn is that dataProvider is sent controller to the view not the other way round. Once you unlearn your backward understanding everything becomes easy.

View sends some sort of form with filter conditions (text, dropdown choices et al) then the controller produces correct data provider by querying the model passing parameters.

then THE CONTROLLER sends dataprovider to the view which displays via GridView widget.

So instead of sending data back to the view, send it back as whatever format you want than HTML (excel file, pdf file or whatever)

Whether you do it on same controller action with flag or separate actions is a matter of taste!

Sorry @evstevemd , what do you mean when say: “So instead of sending data back to the view, send it back as whatever format you want than HTML (excel file, pdf file or whatever)” ?