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

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().

Related

AngularJS how to store client-side only info on a $resource instance

I'm trying to figure out "the right way" to store client-side-only state for an instance of a resource.
Suppose I have an ng-resource, Blerg which has only one data field, "name" and per the docs, I do something like
var blergInstance = new Blerg();
blergInstance.name = "Frankie";
blergInstance.$save();
This results in an http POST to the resource URL with json {name: "Frankie"}. Ok, great.
But I actually need to pass that blergInstance around my client-side application interface for a while, and I want to store some state about that blergInstance to tell the client-side application how to display it or how to interact with it. E.g. I've got a directive that wants to optionally display to the user that "Your blergInstance hasn't been saved yet". Or I've got a button elsewhere that will "Moog this Blerg", and I only want to allow a Blerg to be Mooged once before saving.
My first (admittedly naive) approach would be to do something like
var blergInstance = new Blerg();
blergInstance.name = "Frankie";
blergInstance.saved = false //
blergInstance.hasBeenMooged = false //
// pass the blergInstance around to other services, directives, etc
blergInstance.$save();
But now the http POST looks like {name: "Frankie", saved: false, hasBeenMooged: false}.
So how should I attach "state" to the resource instance that is only relevant to the client-side, and which should not be sent to the server?
Why shouldn't you wrap the resource and state into an simple object and pass around, where resource will have the necessary properties only
var stateful = {};
var blergInstance = new Blerg();
blergInstance.name = "Frankie";
stateful.resource = blergInstance;
stateful.saved = false;
stateful.hasBeenMooged = false;
// pass the blergInstance around to other services, directives, etc
stateful.resource.$save();
Here's an alternative to code-jaff's solution
Warning: coffeescript ahead
Step 1:
Create a service with all your API calls
app.service 'Api', ['$resource', ($resource) ->
{
Blerg: $resource "/api/v1/blerg/:id", {id: "#id"}
....
}
]
Step 2:
Call your Api service and pass in an explicit object
app.controller 'Ctrl', (Api) ->
saveBlerg = {}
saveBlerg.name = Blerg.name
Api.Blerg.save(saveBlerg)

angular callback to application

I am using angularjs & cordova in my app. I am stuck at one point i have an button which is used to authorize a person or user. It sends me to the link where i want to allow the user to access. It is getting access and the url of the link shows that the user is http://(websitename).com/approve but how can i get back the user token into my app so that token can be used for further purpose and second thing how can i send my user from the accessing window back to the app.
HTML code:
<button ng-click="login()">Login</button>
Controller code:
$scope.login = function () {
angular.element(document).ready(function () {
var url = 'https://(website_name).com/1/authorize';
var key = 'My App key';
var callbackURl = 'http://localhost/myApp/';
loginService.login(url,key,callbackURl);
});
factory code:
.factory('loginService', function($http,$window){
return {
login: function(url,key,callbackURl){
var clientURL = url+'?callback_method=postMessage&return_url='+encodeURIComponent(callbackURl)+'&expiration=never&name=myApp&response_type=token&key='+encodeURIComponent(key);
var clientWindow = window.open(clientURL,"_blank");
}
}
})
I want to callback my user along with the token to 'http://localhost/myApp/'
how can it be done or is there any easier way to do such queries??
-thanks in advance.

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.

Reloading a page in angularjs application looses data

Background:
I have a multi page angularjs application. I have a service factory object that I load with values in my initial page. The values loaded to the service factory object are available in the different views or pages via their corresponding controller js. The value provided by the user is lost if the user tries to do a browser refresh by clicking F5 button.
My issue:
When the application is loaded the 'loginView' is displayed, the userId and password entered by the user is passed to the second view (summaryView.html). And i can see the userId and password displayed correct in the second page. But if i refresh my second view (summaryView.html) then I loose all the values. The application is sort of reset.
I would like to retain the user supplied data even after the browser is refreshed or reloaded.
My code:
**index.html**
<div ng-app="offlineInspectionApp">
<div ng-view></div>
</div>
<script>
var mainApp = angular.module("offlineInspectionApp", ['ngRoute']);
mainApp.factory( 'AuthService', function() {
var userCore = {userId : "anonymous" , password: "password", status :"online"};
return {userCore: function() { return userCore; }};
});
mainApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/summary', {
templateUrl: 'summaryView.html',
controller: 'SummaryViewController'
}).
when('/login', {
templateUrl: 'loginView.html',
controller: 'LoginViewController'
});
}]);
**LoginViewController.js**
angular.module("offlineInspectionApp").controller('LoginViewController', function($scope,$http,$location, AuthService) {
$scope.authenticateUser = function() {
AuthService.userCore.userId = $scope.userId;
AuthService.userCore.password = $scope.password;
$location.path( "/summary" );
}
});
**SummaryViewController.js**
angular.module("offlineInspectionApp").controller('SummaryViewController', function($scope,$http,$location, AuthService) {
$scope.syncInspectionDetails = function(inspectionId) {
alert(AuthService.userCore.userId +' '+ AuthService.userCore.password);
};
I have two html files 'loginView.html' and 'summaryView.html'
Flow
1- when the user enter the correct username and password you store the data in angular variables. this is fine and it redirect to summary page. AuthService.userCore has the same scope over the summery page so it displays the details on first attempt.
2- when you refresh the page all the variable you declared in angularJs are cleared. So when you refresh the page you didn't get those variables.
Solution
there are two ways
1- either store the whole user data in cookie, and fetch the data from cookie on refresh.
2- one sign in complition use any access token and store it in cookie. And check for the access token and fetch the data from backend again on every refresh.

AngularJS - Broadcasting across controllers

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.

Categories