I am currently develloping a little app with angularJS;
the users have to go through a login form and then they can click on a few links who display data fetched from a server.
The login form only takes the user's input and it is then "stored" into a factory
app.factory('IdFormHolder', function () {
var that = this;
that.setId = function (data) {
that = data;
};
that.getId = function () {
return that;
};
return that;
});
Which works fine I need to keep it stored because the server requires the login form to be sent each time I do a $http.get as a header.
Each controller takes the login form from the factory and uses it to get the data from the server.
This works fine until someone decides to refresh the page, at which point it seems the factory is "emptied" from its login form, and the web-app then fails to show anything.
Is there a way to store this login info so that it doesn't get erased so easily ?
You can use this code after youve installed sessionStorage:
app.factory('IdFormHolder', ['$sessionStorage', function ($sessionStorage) {
var that = this;
that.setId = function (data) {
$sessionStorage.id = data;
that = data;
};
that.getId = function () {
return $sessionStorage.id;
};
return that;
}]);
Download Link: https://github.com/gsklee/ngStorage
In order to persist data you'd have to use some kind of local DB || LocalStorage || SessionStorage at least. When initializing the Factory you could check and attempt to retrieve from DB/LS that data and hold it as a variable if it does exist.
Something like
app.factory('IdFormHolder', function () {
this.heldId = attemptToGetSavedDataFromSomewhere(); // would be null otherwise
this.setId = (id) => {
this.heldId = id;
};
this.getId = () => this.heldId;
return this;
});
Using angular-local-storage you can access to the browsers local storage:
app.factory('IdFormHolder', function(localStorageService) {
return {
setId: function(data) {
return localStorageService.set('loggedUserData', data);
},
getId: function() {
return localStorageService.get('loggedUserData');
}
};
});
Related
When a user closes or refreshes a browser I would like to save the time to a firebase database and then log them out of firebase.
I can do one or the other using $window.onbeforeunload but fail when I try to do both at the same time.
I can save the time by doing the following:
$scope.onExit = function () {
userRef.update({ lastLogin: Firebase.ServerValue.TIMESTAMP });
};
$window.onbeforeunload = $scope.onExit;
or I can log the user out (using the logout service) by:
$scope.onExit = function () {
logOutService.logoutUser();
};
$window.onbeforeunload = $scope.onExit;
If I combine the two only the first item works (in the example below only the time gets logged)
I have creating as separate functions and combining them but still only the first one works.
$scope.onExit = function () {
userRef.update({ lastLogin: Firebase.ServerValue.TIMESTAMP });
};
$scope.logOut = function () {
logOutService.logoutUser();
};
$scope.combined = function () {
$scope.logout();
$scope.onExit();
};
$window.onbeforeunload = $scope.combined;
Any pointers greatly appreciated!
Update
Ok the above does work if I put the $scope.onExit(); before the $scope.logout(); (I simplified the scenario for the question). The issue happens when I put in a third function like below:
$scope.onExit1 = function () {
userRef.update({ lastLoginPrevious: data.lastLogin });
};
$scope.onExit = function () {
userRef.update({ lastLogin: Firebase.ServerValue.TIMESTAMP });
};
$scope.logOut = function () {
logOutService.logoutUser();
};
$scope.combined = function () {
$scope.onExit1();
$scope.onExit();
$scope.logout();
};
$window.onbeforeunload = $scope.combined;
where the new function is moving the current lastLogin time against a user to the lastLoginPrevious. I am doing this by using a snapshot() to get the data.lastlogin value and this seems to be what is causing the issue as if I change the data.lastlogin to Firebase.ServerValue.TIMESTAMP it works fine with three functions. Any ideas why I cannot use a snapshot() in this scenario?
Update
OK, I got to the bottom of this. I was trying to call data.lastlogin from outside of the snapshot() therefore it wasn't working. Once i nested my functions in the snapshot() it all worked ok.
I want build some simple cache in Angularjs service for data provide from http request. Additional I want always get reference to the same object. I prepare example code to illustrate my thinking and problem which I have now.
jsfiddle code illustrate problem
I have service UsersModel which provide me user from http request.This user data are shared between controllers. So want to have always reference to same data. I add to him simple logic. Before UsersModel.getUsers() call service check if exist any data from previous call, if exist return him, if not do a http request. I inject that service in tree controller. In first two controllers UsersModel.getUsers() is call immediately after page load. In last after click on button.
Problem is when two first controller call UsersModel.getUsers() in the same time. Then any cached data don't exist and both do http request After that I have in first two controller reference to different user objects. We can see this clicking on load button.
And now my question. How to make this work for the simultaneous first call UsersModel.getUsers() and always have reference to the same object data.
app.js
var APP = angular.module('APP', []);
APP.SidebarCtrl = function ($scope, UsersModel) {
var sidebarCtrl = this;
UsersModel.getUsers()
.then(function (users) {
sidebarCtrl.users = users;
});
};
APP.ContentCtrl = function ($scope, UsersModel) {
var contentCtrl = this;
UsersModel.getUsers()
.then(function (users) {
contentCtrl.users = users;
});
};
APP.FootCtrl = function ($scope, UsersModel) {
var footCtrl = this;
function load() {
UsersModel.getUsers()
.then(function (users) {
footCtrl.users = users;
});
}
footCtrl.load = load
};
APP.service('UsersModel', function ($http, $q) {
var model = this,
URLS = {
FETCH: 'http://api.randomuser.me/'
},
users;
function extract(result) {
return result.data.results['0'].user.email;
}
function cacheUsers(result) {
users = extract(result);
return users;
}
model.getUsers = function () {
return (users) ? $q.when(users) : $http.get(URLS.FETCH).then(cacheUsers);
};
});
Index.html
<div ng-app="APP">
<div ng-controller="APP.SidebarCtrl as sidebarCtrl">
<h1>{{ sidebarCtrl.users }}</h1>
</div>
<div ng-controller="APP.ContentCtrl as contentCtrl">
<h1>{{ contentCtrl.users }}</h1>
</div>
<div ng-controller="APP.FootCtrl as footCtrl">
<h1>{{ footCtrl.users }}</h1>
<button ng-click="footCtrl.load()" type="button">Load</button>
</div>
</div>
jsfiddle code illustrate problem
You can modify your functions as follows:
function cacheUsers(result) {
return (users) ? users : users = extract(result);
}
and
model.getUsers = function () {
return (users) ? $q.when(users) : $http.get(URLS.FETCH, {cache: true}).then(cacheUsers);
};
It provides additional cache check after fetch and enables built-in cache for the object.
I suggest you to read http://www.webdeveasy.com/angularjs-data-model/
I'm having some troubles with services in angular.
Basically I have a service that I use as a constant class for user specific parameters, I store these in variables that read the values from a cookie.
This is my service:
shoutApp.service('userConfig', function (userService, config) {
this.USER_ID = $.cookie('shoutUserObj')._id;
this.USER_USERNAME = $.cookie('shoutUserObj').username;
this.USER_PASSWORD = $.cookie('shoutUserObj').password;
this.USER_JOINDATE = $.cookie('shoutUserObj').joinDate;
this.USER_TWITTER = $.cookie('shoutUserObj').twitter;
this.USER_FACEBOOK = $.cookie('shoutUserObj').facebook;
this.USER_GOOGLE = $.cookie('shoutUserObj').google;
this.refreshUserObj = function (callback) {
console.log("Starting refresh");
//This function retrieves new user data
userService.requestUserObj($.cookie('shoutUserObj')._id, function (code, userObj) {
if (code === config.CODE_AJAX_SUCCESS) {
//Here I delete the old cookie and set a new one with the same name
$.removeCookie('shoutUserObj');
$.cookie.json = true;
$.cookie('shoutUserObj', userObj, { path: '/', expires: 7 });
//When I log the new values of the cookie at this point they changed
}
});
}
});
I also tried storing these in an object, but every time I change the paramters they only change inside the class ( Like when i log out the new variables in my refresh function, they changed, but when I try to access them from a controller through the return values, they are not changed).
Example Controller:
shoutApp.controller('profileController', function ($scope, config, userConfig) {
console.log("Username: " + userConfig.USER_USERNAME);
//This value allways stays the same, even when I changed the cookie
});
My goal is to get the changed paramteres in all my Controllers that use the user service, how can I achieve this?
Would be really thankful for any help!
Services are singletons, therefore the values of your userConfig properties will always have the values they had when the service was initialized.
In the service, use a function if you want to retrieve a new value each time
this.getUSER_USERNAME = function() {
return $.cookie('shoutUserObj').username;
}
instead of a property
this.USER_USERNAME = $.cookie('shoutUserObj').username;
then the example controller would be:
shoutApp.controller('profileController', function ($scope, config, userConfig) {
console.log("Username: " + userConfig.getUSER_USERNAME());
//This will return the current value of the cookie
});
I'm working on a controller that reloads data when data is received from a websocket. I've got it working up to the point of reloading the data. I'm not sure why this isn't working, but I'm getting an error when I call self.get('contact').reload(); below. 'object has no method reload'. I'm pretty sure I'm calling this incorrectly, but I'm not sure how to reload the data from the store. Could someone help me out?
CallMonitor.ContactsRoute = Ember.Route.extend({
model: function(){
return this.store.find('contact');
},
setupController: function(controller, contacts) {
var socket = io.connect('http://localhost:3000');
controller.set('socket', socket);
controller.set('contact', contacts);
}
});
CallMonitor.ContactsController = Ember.ArrayController.extend({
socketDidChange: function(){
var socket = this.get('socket'),
self = this;
if(socket)
{
socket.on('call', function (data) {
var contactToUpdate = self.contact.filter(function(item) {
return item.id == data.contactId;
});
if(contactToUpdate.length)
{
contactToUpdate.reload();
}
else
{
// reload all the contacts
self.get('contact').reload();
}
});
}
}.observes('socket')
});
I ended up just doing another fetch from the store and then setting the controller's contact property again. Couldn't find an easy way to do a reload for multiple records. For single records, it's easy to just do a "reload()" but for new records and such it's apparently not that easy.
var contactPromise = self.contact.store.find('contact');
contactPromise.then(function(data){
self.set('contact', data);
}, undefined);
Kind of a bummer. Also couldn't find a good way to remove records in ember data.
I am using amplify.js with Knockout.js and I want to store data locally. I tried using this code: amplify guide
but it isn't working for me.
My view model
define(['services/datacontext'], function (dataContext) {
var store = amplify.store("offlineData"); // Why is agency undefined after retrieving from the store?!?!?!
var agency = ko.observableArray([]);
var initialized = false;
var save = function (agency) {
return dataContext.saveChanges(agency);
};
var vm = { // This is my view model, my functions are bound to it.
//These are wired up to my agency view
activate: activate,
agency: agency,
title: 'agency',
refresh: refresh, // call refresh function which calls get Agencies
save: save
};
return vm;
function activate() {
if (initialized) {
return;
}
initialized = true;
if (initialized == true) {
amplify.store("offlineData", vm.agency);
}
return refresh();
}
function refresh() {
return dataContext.getAgency(agency);
}
});
After refresh retrieves the data, I save this data to the local store. So when I make another request for this page. I would expect var store to contain this data but it is undefined.
Does anyone know how to use amplify?
amplify.store("offlineData", vm.agency);
vm.agency is a function, therefore you need to invoke it to get its value
amplify.store("offlineData", vm.agency());