I have an add form that if the user file the form and submit, in the same time, user can see the data in the same page in table with ui-view and this is not an issue!!
Problem is: if i open more than one tab in the same browser, that post or change reflection doesn't show in other tab without refreshing or reloading. i want to see change in other tab of browser or other browser without reload
I want to see the change without refresh or reloading.
if i reload in other tab, it works but if i dont reload in other tab, the change doesn't effect
here you go for my post method:
$scope.formModel = {};
$scope.onSubmit = function () {
$http.post('http://127.0.0.1:8000/api/v1/contact/create/', $scope.formModel)
.then(function(response) { //if success, below fuction will execute
$scope.successPost = 'You have successfully submitted your Contact';
$timeout(function() {
$scope.successPost = '';
}, 4000);
//below $scope will push data in client site if the request is success
$scope.contacts.push(response.data);
//if any error occurs, below function will execute
}, function(response) {
// below variable will get predefined message that will explain exactly what happened
var errorData = response.data;
$scope.errorPost = Object.values(errorData)[0][0];
$timeout(function(){
$scope.errorPost = '';
}, 4000);
});
$scope.formModel = {}; //It means, after submit, the form field will clear
$scope.addContactForm.$setPristine();
};
I want to see the change in the other tab without refresh or reload
well browser tabs are per definition separated from each other and can't communicate directly between each other.
there are certain possibilities to handle that: for example you can have a separate external service and always poll that service for latest changes and if something changes automatically call reload.
or you could use a service that provide a websocket that sends you to the frontend an update notification once something changed in your data.
Just want to point you in the right direction, the topic is to big to provide a finished solution. I recommend to do some research on how to communicate between tabs / how to build a service with an update notification for new data
Edit: Just to add #Yftach point from the comments: Theoretically localstorage is shared between tabs, so theoretically you could have a variable there and watch in an interval for changes. However the solution with a separate server is (at least in my eyes) way better
Related
I'm writing a small script to capture link clicks and save the link's URL into a database table in order to track how many times each link on a particular page is clicked. The links are to external sites.
So, I capture the click event in my JavaScript function, use jQuery to post to a PHP page that saves the data in MySQL, and then the JavaScript function redirects the user to the URL of the link they clicked on.
The problem I'm running into is that it seems like the post never completes because the of redirect. I've worked around this by calling the redirect inside the post callback, but that adds a few second delay because it doesn't get called until after the post completes. I'm looking for a way to just post the data and redirect the user immediately, regardless of whether or not the post succeeds or fails.
This is the current code with the workaround. It works fine, but adds the delay:
function trackClicks(event)
{
var clicked = $(this).attr('href');
$.post
(
$('#track-click-post-url').attr('value'),
{
action: 'track_landing_page_clicks',
clicked_url: clicked,
nonce: $('#track-click-nonce').attr('value')
},
function( response )
{
window.location = clicked;
}
);
event.preventDefault();
}
And this is what I'd like to do, but when I try it never completes:
function trackClicks(event)
{
var clicked = $(this).attr('href');
$.post
(
$('#track-click-post-url').attr('value'),
{
action: 'track_landing_page_clicks',
clicked_url: clicked,
nonce: $('#track-click-nonce').attr('value')
}
);
window.location = clicked;
event.preventDefault();
}
jQuery doesn't provide a callback for what you're looking for. Here are the available ready states:
Value State Description
0 UNSENT open()has not been called yet.
1 OPENED send()has not been called yet.
2 HEADERS_RECEIVED send() has been called, and headers and status are available.
3 LOADING Downloading; responseText holds partial data.
4 DONE The operation is complete.
You're looking for readystate 2, as that's the earliest you're aware of the fact that the server received the message.
This should get you off the ground:
var xhr = new XMLHttpRequest();
xhr.open("POST", clicked);
xhr.onreadystatechange = function() {
if (xhr.readyState >= 2) window.location = clicked;
};
xhr.send($('#track-click-post-url').attr('value'));
https://developer.mozilla.org/en/XMLHttpRequest for further reading.
Why do you post using Javascript when you are going to load a page any way?
Just update the db with the link clicked on the new page.
Perhaps using the referrer URL to track on what page the click was.
Or some other solution to get on what page the click was (e.g. url param) or some other way.
When you leave a page, all pending requests are killed, and the new page loads. The 1st way is the correct way. Yes, there will be a delay when a link is clicked, that's because the POST request is running.
You can't run a request in the background of a page, if the user is not on that page.
Maybe you can save the link URL in a cookie, and put it into the DB when the next page loads.
is it possible to use angularJs to refresh view's data automatically when the data in database is changed? Please help me how to do it
I made this script, but as you can see the data only refresh if viewData() is triggered.
$scope.viewData = function(){
$http.get("sample.php").then(function(response){
$scope.mine = response.data;
});
}
I want to create page like timeline in twitter which can load new tweets without refreshing the page. Thank you
You can do longpolling like this from Angular side:
setInterval($scope.vievData, 1000);
since setInterval is not monitored by Angular you will have to add the following line in $scope.viewData
$scope.$$phase || $scope.$digest();
immediately after $scope.mine=...
This will refresh $scope.mine every second regardless of the changes in DB, it is a bit crude. To do this only when the values are changed in the database you will probably have to use WebSockets, but that is a bit more complex, both front and back.
HI I'm building out a basic social media site with ionic and am tracking the like counts for each post. On page load I successfully show the like count that is in the db for each record.
$scope.getNewData = function () {
$scope.page = 1;
// get generic feed
FeedService.getFeed(1)
.then(function (data) {
//We will update this value in every request because new posts can be created
// console.log(data.totalPages)
$scope.totalPages = data.totalPages;
$scope.cards = data.posts;
$scope.$broadcast('scroll.infiniteScrollComplete');
return "loaded new data";
})
.then(function (data) {
//$rootScope.$broadcast('newDataLoaded');
})
$scope.$broadcast('scroll.refreshComplete');
};
Issue is after the page loads and another user likes the record I want the like count to automatically update for all users. I started playing around with $interval which works but the whole $scope changes , almost looks like a page refresh. How can I only update the $scope.cards.Post_Likes_Count without having to refresh the entire $scope.cards?
Here is my markup:
<div class="actions-brief">
{{card.Post_Likes_Count}} Likes
<a ng-controller="CommentsCtrl" ng-click="showComments(card)" class="subdued">{{card.comments}} Comments</a>
<!--{{card.shares}} Shares-->
</div>
Ideally I would just want to refresh the $scope.cards.Post_Likes_Count. Not sure how to keep everything in sync if I don't use $scope.cards. I show 10 posts per page but as the user scrolls I grab 10 more records.
Any suggestions or tips would be greatly appreciated.
The whole $scope should not change ... According to best practices, you should make the $http call in factory or service. Lets say you made an http call to your server to update the like done by your one user... You should call activate() function..
Activate function should be a user defined function which makes a request to the server while loading the page to get all the data from database and reload the $scope.yourData variable with latest data.
Moreover you should call the same activate() function from your controller using $interval. This would make your code more structured and proper.
And moreover you should push data in your $scope.YOURDATA variable in your activate() function rather than assigning it each time...
I'm using angular-seed template (AngularJS) and I have routeProvider setup and such, now I want to execute a function (which resides in a factory), but only the very first time when the page gets loaded. I found many solutions for this, but I don't want to execute the code each time the users switches between tabs (via routeProvider of course, page doesn't get reloaded) - the code must be executed only when the whole page gets (re)loaded.
How should I approach this? I tried to call the function from run and then broadcast the event when page gets loaded, but there are no event listeners - I guess that is because the run part gets executed before the controllers are setup, so there are no listeners attached at the time when the event gets broadcast.
So, any suggestions how to approach this?
UPDATE
Use case:
when user types the url in the page, the page gets loaded
when pages gets loaded, a $http.get request is performed, which gets a random content
this content can be changed only by clicking a button, to explicitly request a change of content.
if users clicks to a different page e.g. view2 (routeProvider) and then back to the view1, the content must not change
when users refreshes the page (F5), the content changes again (or as already stated, by a click of a button)
Use the run method:
app.run(function(yourService){
yourService.cacheRandomContent();
});
It runs only once after the app is bootstrapped and services are created.
To access the data in controller, just inject the same service:
app.controller('someCtrl',function($scope, yourService){
yourService.getCachedRandomContent().then(function(resp){
$scope.data = resp.data;
});
});
Your service would be something like:
app.service('yourService',function($http){
var promise;
return {
cacheRandomContent: function(){
promise = $http.get();
},
getCachedRandomContent : function(){
return promise;
}
}
});
Situation:
On one of the views of my AngularJS app I have two pagination buttons that use $http to request the next and previous data. I'm using ng-click="getNext(url)" rather than an anchor tag with href="#/items/:itemId". The reason I'm doing this is so that I can quickly page through my content asynchronously w/o triggering a page reload. This works just fine, but using this method bypasses updating the page's URL so its possible to have your current content out of sync with your URL's id (i.e. path is #/items/3 but you're currently viewing item 9). This can be easily fixed by updating the URL in the JS using $location.path('items/' + rsp.id). Now I can fetch data in an async manner and still be able to refresh, bookmark, send links and have the correct/current item display.
Problem:
The problem with this is if a user hits getNext() a few times and then tries to go back using the browser's back button the URL updates like it should but for some reason the browser doesn't perform a refresh–it just sits there and updates the URL. This only occurs with when the item in history is from the same view and I have updated the ID with the location service.
Any ideas would be appreciated.
What I tried so far
Promises + Flags
I've been playing with window.onpopstate, but as of right now I don't have any way to have window.onpopstate differentiate between a browser click and a UI click that updates the URL with $location.path(); Right now it fires the event regardless of the source. So I tried setting a flag to assume that every time this event fires its a browser event, but when its a UI-based event I can disabled that flag because my _myRequestFn() will handle it. Even with this promise setup it still fires the window.onpopstate when _myRequestFn() is fired.
var flag = true; // Assume all requests are browser-based
window.onpopstate = function() {
if (flag) {
$route.reload();
}
console.log('onpopstate fired');
};
_myRequestFn = function(id) {
someService.getMyData(id)
.then(function(rsp) {
// Do a bunch of stuff including...
$location.path('items/' + rsp.id);
return rsp;
})
.then(function() {
// Everything is done reset flag
flag = true;
});
};
$scope.getNext(url) {
flag = false;
_myRequestFn(url);
};
Spoofing
Hitting back through #/item/5 > #/item/4 > #/item/3 just updates the URL and not the path, but if the history has a different param #/thing/2 > #/item/2 that triggers a page refresh. Since the browser back button works if the history is from a different param I wanted to see if I loaded a different param it would work. So I created an #/item-a and #/item-b route that loaded the same template and used the same controllers, just toggled from a/b with each request. I would never recommend this solution to someone, I was more just seeing if I could get the refresh to trigger.
Update
Lots of people on IRC are suggesting that I use UI-Router. I'm really trying to use the out of the box Angular solution. Refactoring my whole routing setup to use UI-Router is not an optimal solution.
app.config(['$locationProvider',
function($locationProvider) {
// Enable html5 mode
$locationProvider.html5Mode(true);
}]);
From the docs:
In HTML5 mode, the $location service getters and setters interact with the browser URL address through the HTML5 history API. This allows for use of regular URL path and search segments, instead of their hashbang equivalents.