Changes after mass action are not shown in grid
My grid contains a column with a date (in this case: an invitation date).
When I use a Mass action (Static controller method) to send out invitations to my users, the grid is loaded without reflecting the changes to this date. I need re reload my page manually to see the new dates in the grid.
So it seems like the grid data is loaded before performing the mass action and not updated when the mass action has finished.
To me isn't clear what you're asking: a column has a value and you can "only" filter on it. Mass actions isn't related anyhow with this concept.
Try to explain your issue better please and include code and example if needed. Thank you.
Sorry if I wasn't clear enough.
I understand that the columns are not directly related to mass actions, but performing a mass action can change the values that are presented in the columns.
Consider this example, I've got a grid like this:
ID | Name | Email | Invitation Date 1 | Peter | [email protected] | 01-01-2001 2 | Don | [email protected] | 01-01-2001
Now, imagine i have a mass action that resends an invitation and sets the invitation date to today.
When I select the rows, and perform the mass action, the action is executed properly, and the page presents the grid again. I can see in my database that the values have changed.... I would expect the invitation dates to present the new date, but it doesn't. Only when I refresh the page manually, the new invitation date is presented.
So it seems that when I perform the mass action, it first sets up the grid (loading data etc), then executes the mass action (via the handleRequest method), and then presents the grid with data that was loaded prior to executing the mass action.
To further illustrate my issue, here is part of my controller:
`
public function listEmployees(.....){
$grid = $this->createGrid(new ListEmployeesGrid());
$grid->setPermanentFilters(...);
$grid->setDefaultOrder('fullName', 'asc');
$previewAction = new RowAction(....);
$previewAction->setRouteParameters(['id']);
$editAction = new RowAction(...);
$editAction->setRouteParameters(['id']);
$sendInvitationAction = new MassAction(.....);
$sendInvitationAction->setParameters([.....]);
$grid->addMassAction($sendInvitationAction);
$grid->addRowAction($previewAction);
$grid->addRowAction($editAction);
// Handles filters, sorts, exports, ...
$grid->handleRequest($request);
return $this->render('....employees.html.twig', ['grid' => $grid ]);
}
`
I'd like to stress that the grid is working perfectly and the actions are executed perfectly. But I think that the data of the grid is determined before the execution of the mass action and not updated after that execution.
I use this grid in one of my projects and this sound very strange to me: when I perform mass action that change some data on rows displayed in the grid, I always have them back with correct values. I really don't know why of this behavior. Can you perform a debug session with xdebug and follow execution flow?
Alternatively, if you can reproduce this case, please make a GitHub public report with that isolated issue.
Thanks.
Can you post the action responsible of handling the massaction ? I think you have to redirect the user to the action "listEmployees"
@plfort usually mass actions does not return any Response, just perform actions: no redirects, only page "reload" after some logic.
I don't agree :) : https://github.com/APY/APYDataGridBundle/blob/master/Resources/doc/grid_configuration/add_mass_action.md#controller
@plfort I've used it without producing any kind of Response and it works perfectly. What advantage do you have in producing a Response?
I'm using it without a response...
In the add_mass_action.md description it says that a Callback or a closure will return to the grid display. If the Callback or the closure returns a Response object, this response will be displayed.
So it should work fine without a response I guess...
I don't believe my callback does anything out of the ordinary...
static public function sendInvitations($primaryKeys, $allPrimaryKeys, $session, $parameters)
{
$organisation= $parameters['organisation'];
$mailer = $parameters['mailer'];
$translator = $parameters['translator'];
$em = $parameters['em'];
$count = 0;
foreach($primaryKeys as $employeeId){
$employee = $em->getRepository('AppBundle:User')->findOneById($employeeId);
$mailer->send('invitation', $employee);
$employee->setInvitationSentAt(new \DateTime());
$count++;
$em->persist($employee);
}
$confirmationMessage = $translator->transChoice('confirm.send.invitation', $count, array('%count%' => $count));
$session->getFlashBag()->add(
'confirmation',
$confirmationMessage
);
$em->flush();
}
@DonCallisto I just prefer this way instead of a static call
@PeterMuusers
If the Callback or the closure returns a Response object, this response will be displayed.
Yes, it's exactly what it does. Your code seems not have any strange things to me (I've dozen of mass action like your and it all works like a charm)
I found a call to $this->prepare(); in Grid::processMassActions, after which the grid rows are filled with data. This is before the mass action is actually called, so the grid contains 'old data' at this point.
Any 'prepare' calls that are fired after this point are ignored, since the method checks if it has already been called. This means that the data is not updated as the last step in the Grid::handleRequest method.
Since I'm not returning a (redirect) response in my mass action callback, my grid is rendered with the old data in my listEmployees action.
So a possible workaround would be to return a redirect response in my mass action callback. I'm just wondering... do we really need to call prepare() in the processMassActions method?
(Answer: Yes, we need to do that if $actionAllKeys == true)
Yes we need it to get the correct primaryKeys according to the filters