I am working on an angular web application where I want to show the user messages about different actions (like success, failure, etc.). These messages are set to clear automatically after 10 seconds, or when the user clicks the x button beside every alert. This is the easy part.
The difficult part is - I want to maintain these messages when the user navigates to different parts of the application. Something like facebook/google chat boxes.
I initially went through some ideas and decided on a solution where I stored the messages in an array in the local storage and every web page had code to look for these messages and display them if found.
But, I faced issues with the timing of the messages disappearing automatically (the timer reset to 10 seconds for all messages on page load). And also whenever the URL changed, the messages would go away and would load as new alerts after the new web page finished loading.
What is the correct way of doing this?
Whenever an alert appears in your application, you can store its timestamp together with the message. And on the page load call setTimeout for each alert with a callback of removing this message and the time difference between now and the timestamp+10sec.
Using your implementation, the timeout issue is easy to fix: when you store the alert, include an epiresAfter property as well. This property would be a timestamp af when you expect the the alert to no longer display.
Then you set up a timeout that either:
polls and checks the timeout, clearing it if the current time is past the expiration time
or a timeout that triggers after the difference between the expiration time and the current time.
I would consider treating your Message component as a singleton, i.e. it only ever has one instance. If the Message component is a child to other components, then it will be removed when it's parent component is removed from the DOM.
Consider moving your messages component to the root/app level (i.e. inside your AppComponent). This way as the user navigates around your app, the Messages component will always be visible. Further, the state of the notifications can be stored within this Messages component, so it's own timer wouldn't be affected by the rendering/removal of other components.
This all assumes you aren't using some sort of global store for your app state. If you are, consider Hyun Woo Krassilchikoff's answer which details implementing a global NGRX store.
The most efficient way is actually to use an NGRX store for your error message and a unique component in the main layout of your application rendering any message streamed from the store.
You'd need:
an action for pushing any kind of alert:. E.g. PushAlert
an action for clearing the alert. E.g ClearAlert
a reducer for managing both actions above
a selector to stream the portion of the state related the alerts
an effect which triggers ClearAlert 10 sec after detecting PushAlert
a component which displays the alert streamed by the store
Related
i have a logout function that sets the User offline in my DB (mysql), but if it just closes the browser, in my DB the User is still online despite it's not , How can i manage this? How can i set the User Offline without press the logout botton? Cheers in advance !
Ps: Yes, i'm using SESSION
You can do it in following ways.
1) send the Ajax request to server every 5 seconds to update the current time.
2) and where you want to show offline just get records where current time is more than 5 seconds ago.
HI the only reliable way is to set an interval that calls the server and logs it in a database
var timeout = 15000; //milliseconds
setInterval( function(){
$.post('yoursite/keepalive' );
}, timeout );
Then you check the session on the server side you need a simple database table with the user id and a timestamp of the last time keepalive was called, then you just get the current time an there id ( from the session ) and save that. Then you can check if its been more then say like 20 seconds you will know they are gone ( should be updated every 15 sec ). Obviously you would need to have this interval on every page of your site to accurately track a user.
Things such as checking the session time, and unload are not accurate enough,
Unload is fired when any page is closed, so for example,
we have a user that has 2 pages open, they close one of them. the other page is already loaded so there is no traffic between client and server, and no way to know that page is still open
for Session time we have a similar problem, say someone is reading a long post on your page, They need to use the facilities and leave the page open. 30 minutes go by the come back and continue reading the post for another 10 minutes. now maybe the session has expired maybe it hasn't the fact remains they are still looking at your site, and you have no way to know it.
An interval will continue as long as the page is open and there are no javascript issues. A disadvantage of this is it will also keep their session updated ( you can get around this by sending the user id along with the ajax and not using the session, but that has other complications ) because you have that 15 second update you can check anytime if it has been more then 15 seconds. Say you want to display a list of online users to your other forum users, you just query for everyone with a current timestamp from that table, easy beazy.
As for the amount of time for the interval, you have to strike a balance between performance ( network traffic ) and how granular you need to know the information, if it's ok to only know if they logged off within the last minute then use that, if you can wait 5 minutes to know etc....
Really the Crux of the problem is how the server, and a client communicate. Right there is no two way communication like if your on the phone. It's more like a walkies talky where you have to say 10-4 and let go of the button for the other guy to talk. Essentially a client will make a request, that request is fulfilled by the server. that is the end of the communication and the state. Subsequent request state is maintained by using session so the next request uses that session to 'remember' the client. other then that there is no communication between client and server. There is no way to know they hung up the phone, for example, but to ask them if they are still there. ( this is an oversimplification because you cant send a request from the server to ask, more like they have to tell you they are not there, unless you use node.js or something like that ).
As #David has mentioned you could track this based on last activity, for that you would just need to know when the session was last updated. One of the easiest ways is to move the session into a database handler via http://php.net/manual/en/function.session-set-save-handler.php that way you can access when they were last active.
Using this vs ajax really depends on what you need to know, and how accurately. There is also the content of your page to weigh in. If you have a site that makes requests frequently it would be a better approach because you save on network traffic, for example. However, if you have long post someone could be reading for 20-30 minutes but want to know more frequent then that use ajax.
You can do it in many ways:
Launch an AJAX call on onbeforeunload javascript event. Prompting for a confirmation "Windows is closing, are you sure? YES/NO" should give you enough time to set the flag in the db, just be sure that if the user clicks "NO" you should unset your flag
Check session time... Add a var in your PHP_SESSION that is updated at every user event. If it becomes older than a preset threshold (i.e. 5 minutes), you can safely assume the user is gone
Example for onbeforeunload
function myConfirmation() {
return 'Are you sure you want to quit?';
}
window.onbeforeunload = myConfirmation;
You can try the javascript beforeunload event:
window.onbeforeunload = function() {
// Some AJAX request to logout.php or whatever script handles the logout
}
It will trigger when the user attempts to close the current window.
Watch out though, even if the user closes a single tab (your page), the event will be triggered, so if there are other tabs opened, so the browser will be, and you'll still get your users logged out.
Also, if several tabs of your website are opened, and you close one of them, you'll get your users logged out, which may not be what you want, so you'll probably have to find a way around to fix it.
I own a single page application implemented using AngularJs.
Let's suppose my application has 2 pages, sharing the same main top-navbar.
The navbar should display (among other things of course) the current number of unread messages addressed to the connected user, like this screenshot shows:
In my current implementation, while AngularJs starts to be loaded, I trigger in the run method an ajax query to get all the current user's messages (of course, just after the query aiming to check if any user is authenticated).
However, as $http.get is perfectly asynchronous by nature, it is frequent that there is a delay of one or even two seconds (in the worst case, if there are many messages and an additional logic) between the navbar display and the update of number of messages:
............ 1 second later ......
If the icon was a specific page content, I could use the resolve property of the template, but in this case, the navbar is shared by each page.
Should I display some icon representing a "load" of messages while messages are queried to inform user that some messages may be present?
How to deal with this case?
It seems to be the main drawback of single-page-application IMHO.
Indeed, in a non-single page application, the query could happen at server side before server before sending the web page to the client, leading to no delay at all.
I see this as the beauty of single page apps. Rather than waiting seconds for a page to load messages (on the server) that I might not be interested in, it can be lazy loaded giving me instant feedback to perform my desired task.
I would typically go with a directive for something like this and stay off $rootScope, but it sounds like ngShow/ngHide would be able to tie in directly to your setup:
HTML/JADE (classes are just an example)
div#messages(ng-show='messages')
i.fa.fa-envelope-o
span.badge {{messages.new.length}}
div#msgLoading(ng-hide='messages')
Javascript/Angular
.run(function($rootScope, $http, ...
...
//$rootScope.messages has not been instantiated yet
$http.get('//someendpoint').then(function(results) {
$rootScope.messages = results.data;
});
...
I display a list of posts on my page with a like button that the user can toggle on or off.
In order to throttle the traffic with my server, I would like to:
send updates for all the posts where the like status has changed at once in the same request
send updates for the modified posts only
update the like status each N seconds, and on page exit only. Not each time a user toggles a like button.
Is this possible with angularjs?
I've written up an example that can be seen here:
http://plnkr.co/edit/imMGTJ75mKJZT7ispD9E?p=preview
I've spent some time on it with commenting, and providing useful information that gets displayed on the page itself when it runs. Change around the delays if you'd like it to run slower if the messages are moving too quickly.
From your question it looks like you want to save when a user makes any changes to a particular post. You proposed checking every x seconds for changes, but this isn't ideal (though it would be simple to implement with a setInterval). You also mentioned saving the changes on page exit, but it's impossible to guarantee that something happens on page exit (a user loosing power for example).
To avoid the above, I would fire the ajax call when the user clicks the "like" button, but throttle them after the first click & store their changes while the throttle timer is running and push all their changes at once after the timer ends.
Here is what my plunker code does in a nutshell:
User "likes" or "unlikes" a post and it will make an Ajax call to the server with the new information on the post. At this point, any new "likes" / "unlikes" gets thrown into a "queue" of posts that need to get updated.
When the first Ajax call is successful, the throttle timer starts. In the example I've provided it is 5 seconds. Any changes to a post ("likes", "unlikes") will be thrown in that same "queue".
After 5 seconds is up, it will check the "queue". If it's empty, no action is taken. If it has items in it (e.g. posts that have changed), then it will make a second ajax call and update the posts on the server.
My example won't mirror what you're working on exactly, but it's the concept that matters. You could modify the code so it doesn't throttle for such a long time, or have it only throttle after x number of ajax calls in a certain amount of time, etc.
This question probably doesn't have an answer. But, I thought I'd give it a shot.
I wrote a great one-page application. When the application starts up, the open tab "registers" itself with the server, which stores is as an "active" tab.
If user A changes XYZ in the workspace, every tab opened on that workspace, by any user, receives a notification that XYZ was changed. That triggers a reload in the clients, which will magically be updated. At the moment, I am doing this by polling. However, when it all works I can use things like WS or Socket.io to make things even faster.
PROBLEM: every tab receives the notification. Even the tab that instigated it in the first place! (as a result, an already-updated screen gets updated)
I somehow need the server to know the tab ID of the tab making the request. Remember that a user might have 5 tabs open: if they change XYZ, all tabs should receive the notification, EXCEPT the one that actually triggered it!
At the moment, I am passing the workspace ID for every Ajax request ( a user might be logged in, and have access to several workspace at the same time).
Solution 1: append both workspace ID and tab ID for every request
Solution 2: only use the tab ID for every request. The app will work out the workspace ID from the tabID (which knows which workspace it belongs to)
Solution 3: ????? (Something that I am missing?)
Any ideas?
Instead of having the server worry about which tabs to send change notifications to you could have the tab that initiated the changes ignore the notification.
Two ways to do this come to mind:
After changing the content a tab will ingore all notifications for a brief period of time. (This will work fine unless changes on multiple tabs happen in a short amount of time.)
Have the tab create a "change id" that it sends to the server with the changes to xyz. The broadcast change notification contains this id and the sending tab recognizes it as the one it sent and ignores it.
You could experiment with HTML5 Visibility API with a fallback to window.onfocus & window.onblur events and suppress updating the page if it's currently visible/active.
In the past, when I've covered events, I've used a meta-refresh with a 5 minute timer to refresh the page so people have the latest updates.
Realizing that this may not be the perfect way to do it (doesn't always work in IE, interrupts a person's flow, restarts things for people with screen readers, etc.) I'm wondering if there's any other way to do handle this situation.
Is it possible to have something like ajax check every few minutes if the html file on the server is newer and have it print a message saying "Update info available, click here to refresh"?
If that's crazy, how about a javascript that just counts down from 5 minutes and just suggests a refresh.
If anyone could point me to tutorials or code snippets I'd appreciate. I just play a programmer on TV. :-)
Actually, your thought on a timed Ajax test is an excellent idea. I'm not sure that is exactly what StackOverflow uses, but it checks periodically to see if other answers have been posted and shows the user, on an interval, if there are updates.
I think this is ideal for these reasons:
It's unobtrusive - the reader can easily ignore the update if they don't care
It won't waste bandwith - no reloading unless the user chooses to
It's informative - the user knows there's an update and can choose to act on it.
My take on how - have the ajax script send off the latest post id to a script that checks for new scripts. This script can query your database to see if there are any new posts, and how many there are. It can return this number. If there are new posts, show some (non modal) message including the number of updates, and let the user decide what to do about it.
setInterval(function() {
if (confirm("Its Been 5 Minutes. Would you like to refresh")) {
window.location.reload(true);
//Or instead of refreshing the page you could make an ajax call and determing if a newer page exists. IF one does then reload.
}
}, 300000);
You can use the setInterval function in javascript.
here's a sample
setInterval("refresh function", milliseconds, lang);
You will use it passing a name to a function that actually refresh the page for the first param and the number of milliseconds between refresh for the second param (300000 for 5 minutes). The third parameter lang is optional
If the user would be interacting with the scores and clicking on things it would be a little rude to just refresh the page on them. I think doing something like a notification that the page has been updated would be ideal.
I would use jQuery and do an ajax call to the file on the server or something that will return the updated data. If it's newer than throw up a Growl message
Gritter - jQuery Growl System
Demo of what a Growl is using Gritter
A Growl message would come up possibly with whatever was changed, new scores and then an option within that message to refresh and view the new results.
jQuery Ajax information