AngularJS - Broadcasting across controllers - javascript

Am trying a scenario where i Login, and, on success, want to store that LoginID and pass it to all other controllers for navigation/user management. Similar to a global variable set up, store once use everywhere concept.
Been using angularjs shared Services technique but its not picking the braodcaster LoginID in other controllers.
High level details:
1) Login HTML calls Login Controller from where i call back end server for user authentication
2) On success, broadcasted LoginID via shared service
3) from Login HTML, page navigates to OrderMenu Html and calls OrderMenu controller where am trying to fetch the User id which was broadcasted via the shared service.
4) but in the Order Menu controller the UserID shown is the initialized value i.e looks like app.factory is being called again and initializing the Broadcasted value.
I want to stop the reloading of app.factory. Looks like am missing something here.Any thoughts would be really helpful here.

Here is a quick implemention example of what you described.
And it seems to be working.
http://plnkr.co/edit/SPAB4W
My service is defined as follows:
app.factory('UserAuth', function() {
return {
userId: 'unknown',
authenticate: function( name ) {
// do server side authentication here...
this.userId = 'authenticatedUserId_Of_' + name;
}
};
});
In this example, when second controller (OrderCtrl) is getting called,
UserAuth.userId does not get re-initialized
and keeps the obtained userId of what authentication gives.
You may want to share your code.

Related

Is there any way to render freshservice app on portal pages (Requesters view)

My Requirement is
1. User will type subject.
2. On the basis of subject, I want to call third party rest API (Currently being blocked by CORS. even the jsonp request is also not working)
3. I want to set some field values on form according to the response
You cannot render an Freshservice app from the customer's view (User/Employee/Requester) as of now. Instead you can create Freshservice app on Agent portal where tickets are managed.
Create a serverless app.
On onTicketCreate product event you can write in your logic in server.js:
exports = {
events: [{
event: "onTicketCreate",
callback: "onTicketCreateCallback"
}],
onTicketCreateCallback: function(payload) {
console.log("Logging arguments from onTicketCreate event: " + JSON.stringify(payload));
// 1.Implement the logic with the help of payload's ticket subject that you are looking for.
// 2. To shoot bypass CORS use platform's request API - https://developers.freshservice.com/docs/request-api/
// 3. Update the Fields using - https://api.freshservice.com/v2/#view_a_change
}
}
See this reference for making changes to agent facing field values.
In simple terms this process results to fill in fields as per your use case. Only difference is, it happens on creating a ticket but not while filling up the requester facing form.

How to share data among the controllers using $broadcast, $on and $emit?

I am new to AngularJS web development.
STEP 1. During initialization, I get login information from a server with http call. Say, UserName, UserID and some other information.
STEP 2. After successful http call, I would like to populate the loginObj object such as
$scope.loginObj = { UserID = '', UserName = '', SomeData: '' };
$scope.loginObj.UserID = 1000;
$scope.loginObj.UserName = 'John Doe';
$scope.loginObj.SomeData = 'Some other data';
STEP 3. I would like to broadcast $scope.loginObj object information with
$rootScope.broadcast method.
All the examples I have seen used some kind of click button. No Button Click
solution.
STEP 4. In the child controller, I would like to receive the broadcasted
information from the Parent Controller.
How can I receive this information?
STEP 5. Some times I get some extra information at the Child Controller as well.
How can I receive this information from Child controller to the Parent
Controller?
Please provide me a solution or direct me some sites where I can get the example.
Instead of using broadcast, create an angularjs service in which you persist the login info you got from http call and you can inject this service in the controller in which you need login info.
create a service like this :
/*app is your angular module name*/
app.factory('authFactory',['$state',function( $state){
var authFactory = {
currentUser: {},
setCurrentUser: function(userinfo){
authFactory.currentUser = userinfo;
},
getCurrentUser: function(){
return authFactory.currentUser;
}
};
return authFactory;
}
in your login controller, inject authFactory, then once user is logged in, call authFactory.setCurrentUser and pass an object ({login: userlogin, email: useremail}). if you need the logged in user in another page, just inject authFactory in that page and call authFactory.getCurrentUser().

Calling the app config method inside ajax response - AngularJS

I am developing an app using angularjs and this is my first hands on using angular. Although, I have started understanding it and have developed some part of the app but I am stuck at one particular point.
I am trying to implement login functionality, so as the page loads, I am authenticating user and redirecting him to login page. On successful login, I am storing some values of user in one of the config provider.
Now I am using an API which has their own method of authentication and they have expose the ajax method which I can use to authenticate a user.
I have provided a snippet below. What I am primarily doing is using the external API, authenticating the user and once authenticated, I am getting roles associated to that user using another ajax method of the API, called "GetUserDetails".
And inside the response of the "GetUserDetails", I am injecting a provider and setting some values, so I can use this across my app.
The problem here is the app.config method is never called/executded. I mean the ajax request is returning response, and the alert is displayed on my page, but app.config is never executed.
But the same app.config if I call inside the done() of GetUser method, the app.config gets executed and stores values in my provider. But I want the GetuserDetails values also to be stored before I do anything in my app as I want to execute certain functionality based on user.
Below is my function in main.js file
function(angular,angularRoute,app,routes,configService){
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.element().ready(function() {
$.c.authentication.getUser()
.done(function(response){
if(response.userName!="anonymous"){
$.c.ajax({
method: "GetUserDetails",
parameters: {
User: response.user
}
})
.done(function(res) {
alert("I have reached the destination").
app.config(['configServiceProvider', function(configServiceProvider){
configServiceProvider.setLoginStatus(true);
configServiceProvider.setUserName(response.userName);
configServiceProvider.setUserObject(response);
configServiceProvider.setUserRoleDetails(res);
}]);
})
.fail(function(res) {
alert("Error while getting user roles ."+res);
});
angular.resumeBootstrap([app['name']]);
}
else
{
app.config(['configServiceProvider', function(configServiceProvider){
configServiceProvider.setLoginStatus(false);
configServiceProvider.setUserName(response.userName);
}]);
//Show Login Screen
var url = window.location.href.split("#")[0];
window.location.href = url + "#/Login";
angular.resumeBootstrap([app['name']]);
}
})
.fail(function(response){
$rootScope.isLoggedIn=false;
});
});
Here is my configServiceProvider
define(['../app'],function(app){
return app.provider('configService', function(){
var options={};
this.setLoginStatus = function(status){
//$rootScope.isLoggedIn = status;
options.isLoggedIn=status;
};
this.setPreLoginInfo=function(info){
options.preLoginInfo=info;
};
this.setUserName=function(name){
options.username=name;
}
this.setUserObject = function(userObject) {
options.userObject = userObject;
}
this.setUserRoleDetails = function(userRoleDetails) {
options.userRoleDetails = userRoleDetails;
}
this.$get=[function(){
if(!options){
}
return options;
}];
});
})
Can anyone please explain me what's going wrong here or what I am missing ?
Also, is there any alternative to achieve the same functionality ?
No luck in figuring out why the above scenario was not working. Since I had already spent lot of time behind this, I have found a workaround to achieve the same with the use of services.

The ui-router for angular seems to be cacheing the resolve. When I don't want it to

The Background:
I am using ui-router for my Angular page routing needs. It's working great so far, however I'm running into an issue. When I load a state and I resolve my user object. I use restangular to make the call to the database and it returns a promise. Everything works great. If I then log out, and log in as another user. Then navigate back to that same page it shows the previous user object.
Things that I've discovered:
The rest api call is being made every time when the state loads, and
it is the correct information.
If I place a break point inside my controller the user object that the resolve passes is the cached
information.
Theories:
The rest API end point is /users/me/, which is the same end point for
every user. We just deliver different information based off of the
JWT token we pass. Somewhere must things since it's the same call
don't bother delivering the goods it already got.
Things I've tried:
I've confirmed that the API call isn't cached, and it is delivering
the correct information to angular
I've tried grabbing the
$cacheFactory of $http and .removeAll.
Sample code:
angular.module('services.user', [ ])
.factory('User', function(Restangular) {
return Restangular.service('users');
});
angular.module('settings.profile', [
'ui.router',
'services.user'
])
.config(function($stateProvider){
$stateProvider
.state('settings.profile',{
url: '/profile',
templateUrl: 'app/settings/profile/settings.profile.html',
controller: 'SettingsProfileCtrl',
authenticate: true,
resolve: {
user: function(User) {
var user = User.one('me').get()
return user;
}
}
});
})
.controller('SettingsProfileCtrl',
function($scope, $location, user, $http, apiUrl){
$scope.user = user;
}
I had the same problem, however in my case the data requested in the resolve property wasn't coming from an API so HTTP caching definitely wasn't the problem.
I added {reload: true} for the options property in the troublesome $state.go call and this seems to have forced ui-router to refresh the resolve property. I no longer get the previous user's roles and permissions, which is nice :)
Your REST API parameter does not change i.e. it stays the same /users/me/ in all the requests. While the browser may not cache - which is why you see different correct information the cache.
You can try configuring Restangular to validate the theory by doing as below:-
RestangularProvider.setDefaultHttpFields({cache: true});
However I advise you to use URLs and REST API in the spirit of REST style i.e. use something like...
/users/me/username
where username changes based on the user OR if you have some constraints do the following
/users/me/?t=timestamp
Try adding cache: false to the state configuration object. But I also recommend adding a different parameter to the requests like userId for example.

How to handle user information using firebase simple login for facebook

I am building a webpage using AngularJS and Firebase. I want to use facebook login to connect information on the webpage with the user. Firebase has a version of simple login which I guess is supposed to simplify the login process.
My problem is that I want to access information about the logged in user in a lot of places on my webpage but I can't find a good way to do it.
This is how I started out:
var userInfo = null;
var ref = new Firebase('https://<yourfirebase>.firebaseIO.com/');
var auth = new FirebaseSimpleLogin(ref, function(error, user) {
if(error)
alert("You are not logged in");
else if(user)
{
//store userinfo in variable
userInfo = user;
}
else
//user logged out
});
//do something with userInfo
alert(userInfo.name);
My first thought was to run this at the top of my page and then use the info about the user. The problem is that the code using userInfo (as in e.g. the alert) will always run before the userInfo variable has been filled and userInfo will return undefined/null.
I then proceeded to always create a new firebasesimplelogin object when i want to retrieve user data. Which of course isn't very good. Especially since every created FirebaseSimpleLogin object will be called again whenever another is called or a user logs out, for example.
So my question is, how do I use FirebaseSimpleLogin to handle and use my user information in the best way?
I would have liked some function to getUserInfo() or check isLoggedIn() for example. How do you do this properly?
You can take a look at this example for thinkster. It's based on using simple login with userid/password. http://www.thinkster.io/angularjs/4DYrJRxTyT/7-creating-your-own-user-data-using-firebase.
You can create a function like getLoggedinUser that runs in $rootScope that will allow you to find the user throughout the application.
UPDATE:
Around the middle of October 2014, firebase made some big changes. This method might still work, but it's better to take advantage of the newer version of firebase, specifically getauth and onauth. These methods will allow you to do the same thing without running on the rootScope. https://www.firebase.com/docs/web/guide/user-auth.html#section-login
Please make a constant to use it everywhere in your App like that
.constant('facebookUrl', 'https://rjrestaurantapp.firebaseio.com');
Then in the controller inject this constant "facebookUrl & "$state" as shown below...
.controller('loginCtrl', function($scope,facebookUrl,$state){
and then you only need to give name of the state where you want to redirect after facebook authentication..
var ref = new Firebase(facebookUrl);
$scope.fbLogin = function () {
ref.authWithOAuthPopup("facebook", function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
$state.go('restaurant');
}
})
}})
You can see the information in authData object after successfull authentication using facebook ....
please read this doc carefully https://www.firebase.com/docs/web/guide/login/facebook.html
The above is the example of simple login using firebase and for retrieving data for each logged in user, you have to store user information at the time of signin as you know that firebase makes every child with a unique ID .. then you only need to use the offline features of firebase that will find which user is offline and according to that remove the node with the same ID which one is offline, you can find examples in the MANAGING PRESENCE section of the below link ..
https://www.firebase.com/docs/web/guide/offline-capabilities.html

Categories