Reputation: 5404
I have an application written in CakePHP 3.5.13
It makes use of the Flash Component built into Cake. All of this is working when configured in the standard way, e.g.
// src/Controller/SomeController.php
public function foo()
{
$this->Flash->set('Records updated', ['element' => 'success']);
return $this->redirect(['action' => 'index']);
}
// src/Template/SomeController/index.ctp
<?= $this->Flash->render() ?>
So if I access /some-controller/foo
it will set the flash message, reload index.ctp
and display it.
However, I want to modify things so that it's all done via ajax calls.
If I create a new template, /src/Template/SomeController/index.ctp
and use the following jquery:
$('.foo-test').click(function(e) {
e.preventDefault();
$.ajax({
url: '/some-controller/foo'
}).done(response) {
//console.log(response);
window.location.href = '/some-controller/index';
});
});
When I click on an anchor with the class .foo-test
it will make the ajax request.
But reloading the page (window.location.reload
) doesn't display the flash message. Why is this, because that's equivalent to the browser reloading /some-controller/index
, right?
The only way I can think to modify this is to have foo()
return a JSON response. Where I've used console.log(response)
I could then access the response data and determine the outcome, then add the flash message, e.g.
if (response.success !== '') {
$('#outcome').html(response.success).addClass('alert alert-success');
}
Which would write the response message to a div with the ID #outcome
and add the appropriate classes for styling purposes.
Surely there is a better way than this, as it would involve rewriting every single method where I needed to do this?
Why doesn't executing the controller function followed by reloading the page with jquery work, bearing in mind it can still access the $_SESSION
when doing things in this way?
I have looked at plugins but want to know if there's a native Cake way to do this that I'm overlooking? Ajax isn't mentioned in the Flash Component docs.
Upvotes: 1
Views: 1761
Reputation: 5404
Ok, I've figured this out, with help from @ndm in the comments.
The solution is to remove the PHP redirect in SomeController::foo()
:
public function foo()
{
// There is no template (foo.ctp) associated with this function.
$this->autoRender = false;
$this->Flash->set('Records updated', ['element' => 'success']);
// Remove line below:
//return $this->redirect(['action' => 'index']);
}
This is because we're doing an equivalent redirect in jquery:
window.location.href = '/some-controller/index';
So the ajax request to /some-controller/foo
still sets the flash messages. Using the jquery redirect reloads index.ctp
which then has the code to render the flash message.
If you're refactoring code to do things in this way, you need to make sure the action equivalent to foo()
in this example just sets the flash messages and does not output anything. You can achieve this with $this->autoRender = false
and then use $this->Flash->set()
as normal to set your messages.
Upvotes: 2