flash messages on multiple pages is not working
SrividyaKasu opened this issue · 17 comments
When I have flash messages in consecutive views, flash message on second page is not shown. Please check the below code. flash to strategy also is not working(
flash.to('alert-1').info = 'Only for alert 1';) It seems like page 1 swallowing flash message destined to page 2.
Page 1
Page 1 controller
flash.success = 'Deletion was successful.';
Page 2
You're dealing with different scopes. In it's current form, angular-flash cannot flash.to() a DOM element that doesn't exist (yet). If you attempt to flash.to() an element on the page of your current scope, you'll see that it is working.
I was having the same issue, so I simply created a catch-all alert (not assigning an id to the alert element) on the second page.
@mark : Thanks for you response. Even catch all alert is not working on second page. If I remove {{flash.message}} div element in the first page, then flash message works in second page. Its like I can either one of the flash message, not both.
Hi @SrividyaKasu,
Thanks for posting this issue. Can you provide more detailed HTML and JS snippets of page 1 and page 2 and controller 1 and controller 2?
Thanks,
Luke
Hi Luke and Mark,
I work for the same company as Srividya. I attempted to fix this problem and have a patch that seems to work and is compatible with the existing functionality. (As much as I can see.)
I've created a pull request please revise and perhaps approve if you find it useful.
Best regards
Marton Tatai
Hi Marton,
Thanks for the PR, but before we go there I'd like to get a better understanding of this issue.
Please include some more detailed template and controller examples so that I can dig deeper.
Thanks again,
Luke
Hi Luke,
Thanks for your reply. I've compiled a package with the example files. They are commented and I've deleted most of the content to make it simpler and more transparent.
http://www.sendspace.com/file/azl4pa
If I've deleted too much or you need more information please let me know.
Generally the problem is that when there is a message box on the page we are navigating away from the hooked $destroy event gets rid of the message we set in the controller before we navigate away from the page. That's what my PR attempts to fix.
We want to keep the flash message until it is consumed on the next page. I suspect this library wasn't exactly intended to be used this way, but the changes in the PR don't "fix" this, it just provides a way to go around it.
Regards
Marton
Hi Luke,
I do not mean to rush you, I just wondered if you perhaps had a chance to look at the ZIP file I have sent, or you need more information from us?
Regards
M
Hi Marton,
Thanks for following up.
Admittedly, I've been preoccupied learning how to be a first time father. The online docs for these newborn platforms isn't so great ;-).
Fingers crossed, I'm hoping to get caught up this weekend.
Thanks again for contributing.
Luke
On Apr 16, 2014, at 2:01 PM, Marton Tatai notifications@github.com wrote:
Hi Luke,
I do not mean to rush you, I just wondered if you perhaps had a chance to look at the ZIP file I have sent, or you need more information from us?
Regards
M—
Reply to this email directly or view it on GitHub.
Haha, that is fantastic, congratulations!
Take your time, first thing first.
Best regards
M
Hi Luke,
Is there any chance you will be able to review the pull request anytime soon?
Bests
M
Any updates on this? I have the same issue.
I'm having flashes in both views (basically its the same view with a $route.reload()
).
Its the Edit page of a model. When I want to update the model I set a flash and reload the page to reduce the state changes in the controller.
The flash on the first page receives the message and directly cleans in on the destroy event.
The second flash never sees the message.
The code looks a bit like this
function Controller($scope, $route, flash) {
$scope.submit = function() {
// Model update omitted for brevity.
flash.success = 'Model updated';
// Easier to reload all models and the changed
// dependencies than to keep track of state.
$route.reload();
};
}
Hi Mark,
If you want you can clone my branch then use it something like this.
function Controller($scope, $route, flash) {
$scope.submit = function() {
// Model update omitted for brevity.
flash.success = 'Model updated';
flash.cleanOnReload = false;
// Easier to reload all models and the changed
// dependencies than to keep track of state.
$route.reload();
};
}
It will carry your message on to the next page or until reload.
Bests
M.
Hi Folks,
Sorry for the radio silence. I've been pondering how to best support this behavior.
Initially, I envisioned angular-flash
as a simple realtime pub/sub pattern with little to no state and persistence.
But it seems that you guys would like to use it more like the HTTP session flash pattern popularized by rails flash. With Rails, the flash message is persisted within the HTTP session and then displayed and removed with the next HTTP request. So Rails flash involves state and leverages the the HTTP request cycle to determine when to show and remove the persisted flash.
In contrast, angularjs apps (single page HTML5 apps in general) don't have a common request cycle and session state to leverage. For routing, some apps use angular-route
, others use angular-ui-router
, and others don't use routing at all. Likewise for session, some apps use localstorage
, some use IndexDB
, some use in-memory hashes, and some don't have a session at all.
Admittedly, the name angular-flash
implies that it should operative like a traditional HTTP web app flash service. And I'm dreaming up better ways to support this behavior in v2.0.
In the meantime, I can bake-in something like flash.on(event)
, where event
can be either an angular scope event, such as $routeChangeSuccess
, $destroy
, and $stateChangeSuccess
; or a callback with parameters: notify
, type
, and message
.
Here are some examples:
// Publish this `success` alert after the next `$routeChangeSuccess` event.
flash.on('$routeChangeSuccess').success = 'Hello from the previous page';
// Roll your own event callback: Publish this `info` alert after this scope is destroyed
function onDestroy(notify, type, message) {
$scope.$on('$destroy', function () {
$timeout(notify);
});
}
flash.on(onDestroy).info = 'bye bye from about page';
Thoughts?
Thanks again for your patience and continued feedback,
Luke
Hey @wmluke I also intended to use it for multiple pages. Did you end up implementing this, or is there any workaround to do this right now?
My solution is to have a separate HeaderCtrl
for all things common across my app: navbar, sidebar, and flash messages. Then, even when my route (well, state since I'm using ui-router
), changes, the messages persist since that part of the page isn't affected.
EDIT: More details.
<body>
<div ng-controller="HeaderCtrl">
<nav><!-- etc. --></nav>
<div id="messages">
<div flash-alert active-class="in alert" class="fade">
<span class="close" ng-click="hide()">
×
</span>
<strong class="alert-heading">FYI.</strong>
<span class="alert-message">{{flash.message}}</span>
</div>
</div>
</div>
<div id="main" ui-view></div><!-- or ng-view if you prefer -->
</body>
app.controller('SomeCtrl', ['flash', function (flash) {
flash.error = 'Check yourself before you wreck yourself.';
}]);
Actually, there's no reason to have the separate control: as long as the flashAlert
directive is outside your uiView
or ngView
, it shouldn't be affected when moving from view to view.
Just to chime in, I ended up using @StevenClontz's solution and it worked well. This feels more like the "correct" way to do it, as opposed to some blob of data persisting throughout navigation events.
Instead of always having to use angular-flash in a high-level scope (above the view/ui-view), why not retain the messages in the angular-flash service, like in angular-flare? It wouldn't force a particular design pattern and would let one access the flash messages without the worry of them getting nuked with the directive.