AngularJS Calling function in controller after data is loaded in another file - javascript

I have this function in app.js which connects to an api using promises. The app that is selected to be opened depends on the user ID.
me.boot = function () {
me.getUserID().then(me.openAppFunction);
};
Also, I have this function in my Home.js controller
getObjectsFromApp();
This function needs to be executed after the application is loaded in the other file, but I have no idea how to do this. This app.js file is not a service or a factory, it is just a file that is called when the application loads all the scripts with require.js. The only thing this file does is select which app to open in the api, so that is why it is only called once.

An Event is probably what you are looking for...
You should stay in the angular environment, so, you should use $rootScope.$broadcast and $rootScope.$on and they can be used everywhere in your application because $rootScope is singletone.
this Why do we use $rootScope.$broadcast in AngularJS? could help you.

Related

Where to place init code with Angular 1?

I have an angular web application that is currently calling the backend API every time I need to display the user name or user image. However, I would now like to be able to cache this information in localStorage when the application is first started. What would be the best way or best place to do this in Angular? I image it would be something equivalent to the jquery $(document).ready method. Any hints would be appreciated.
You could put it in the run block. This will run once when your app starts up
angular.module('myApp').run(function () {
//Run init code
});
While you can use module.run for this, a better option would be a thematically related service. Angular services are created once, and so you can just put your loading code on the top level.
E.g.
angular.module('myApp').service('currentUser', function() {
// load user data from local storage, if not found load from server
// then store in localStorage
this.name = /* loaded name */;
// etc...
});
Note that most of requests are asynchronous, so you might want to do a factory that would return a user promise instead.

AngularJs: Sharing data across controllers

I am using super heroic Angularjs in my application. I have a couple of pages like home.html, project.html, map.html. Each pages has a controller associated with it e.g. HomeCtrl, ProjectCtrl, MapCtrl. In my home.html user can create a project or navigate to project.html. In project.html I have list of all projects. When user clicks on a project he is navigated to map.html where I have some information regarding to project. I am using ngRoute for routing between the views. I am facing some challenges to share data across the controllers. I have created a service called dataFactory which stores all the data retrieved from backend. In my project.html view, I load all the data from backend and store them in service. When user lands into a project I use data stored in the dataFactory. The concern is that when user refreshes the page when he is on the map.html, all the data which are stored in dataFactory are wiped out and not loaded back cause data loading happens in the project.html page. I don't know how can I deal with it. I can not make a call to backend in every controller to get the data. I am planning to load the common data in app.run() method. But in that case I have to broadcast/emit the events to notify controllers, which will also be messier and will eventually lead to errors cause I know my application is going to be a huge application.
There is a solution but it needs some additional configuration while making routes in your $routeProvider, You can resolve your route when you have your data fetch from the backend. By using this method if a user refreshes the page on one of your project it will receive the data first then display that particular page.
First you have to modify your dataFactory something like this
app.service('MyService', function($http) {
var myData = null;
var promise = promise || $http.get('data.json').success(function (data) {
myData = data;
});
return {
promise:promise,
doStuff: function () {
return myData
}
};
});
Then in your $routeProvider you could make route to resolve when your data is fetched (that is receives its promise) more over by using this method it wont make another data call if your data is stored.
app.config(function($routeProvider){
$routeProvider
.when('/',{controller:'MainCtrl',
template:'<div>From MyService:<pre>{{data | json}}</pre></div>',
resolve:{
'MyServiceData':function(MyService){
return MyService.promise;
}
}})
.when('/b',{controller:'MainCtrl2',
template:'<div>From MyServic2e:<pre>{{data | json}}</pre></div>',
resolve:{
'MyServiceData':function(MyService){
return MyService.promise;
}
}})
})
I've a made a working Plunker for demo. Fell free to ask any question regarding this.
Hope it helps.
when you refersh the page, the app module loads again wiping out all the stored vars. You can use sessionStorage or localStorage to maintain data.
When you store your data into service/ factory store it in to your browser's local storage too. So, when user refresh the page, you can check whether your local storage has the data or not. If there is data in your local storage just save these data into your service/ factory.
That's all !!!
If you are struggle to implement these things please update me, I can help you on the code also.

Angular bootstrap lifecycle: Run code after full load

Angular defines a run() block for an application module. This runs after config() and before any controllers and directives are loaded.
Is there a step in the lifecycle to run something after all controllers, directives, services, etc are loaded?
I need this in order to broadcast a message in my authorization pubsub service, and I want to ensure that everything is loaded before I publish the message. While I can check authentication in the run block (basically, just checking localstorage for a JWT via my authentication service), if I publish in the run() block I can't be sure if everything has loaded. I'm wondering if Angular exposes anything like this or whether I need to find a different solution.
Thanks!
An optional answer, taken from here
You can use a custom postDigest callback. if you need only the first postDigest callback, add a flag to indicate it happened
function postDigest(callback){
var unregister = $rootScope.$watch(function(){
unregister();
$timeout(function(){
callback();
postDigest(callback);
},0,false);
});
}
postDigest(function(){
console.log('do something');
})

Code organization (node, js involving models, service, route and mocha tests)

I'm quite a beginner in the project architecturing / structuring side of things.
The overall project currently looks like:
route/home.js
service/appService.js
models/appModel.js
In the route file, I require appService.js.
appService.js takes care of some API calls to external services, such as getting an access_token from such API service.
When I receive the access token, a callback is made in appService which calls appModel (appService requires appModel.js), and in turn appModel stores the access token in the database. Then, another callback is called in appService which in turn does runs the callback that the route page provided, then I make a redirection.
I am using mocha for testing the service and model files.
My service file is requiring the model file, so when I create a mocha test for the service file, the model is called indirectly as well.
Should I require the model in my route file instead of the service file, and run the model function in the route, once I receive the access token response from the API in the service file? What do you suggest?
Normally you would have some kind of bootstrapper or service container which handles loading your files.
That way you avoid tight couplings between the different parts of your application and can exchange them out when testing (such as swapping the DB for fixtures).

Syncronizing Session data with other angular directives and controllers

In my AngularJS application, I have a Session service object that contains stuff like the current user, their preferences, the current company they belong to, and the current theme that they are using. Many places in my application refer to the Session service when they need to get at this data.
Because these variables are in a service, I cannot use scope watches to detect changes. So instead, I've decided to use the observer pattern. Various places in the application, such as other services, directives, controllers, etc. will register themselves with the Session service and provide a callback to be executed whenever the Session changes.
For example, if the user changes their theme, the <style> element in index.html that uses a custom directive will be notified, and it will recreate all of the overriding css rules for the new colors.
For another example, whenever the user's avatar is updated, the main menu bar controller will be notified to refresh and redraw the avatar. Stuff like this.
Obviously the data in Session has to be refreshed at least once before the various controllers, directives, etc. use it. The natural place to ask the Session service to get its session data was in a run block for the application-level module. This works pretty well, but I don't think it's the best place either.
One problem I have noticed is that when Firebug is open, the asynchronous nature of things loading causes ordering issues. For example, the directive that runs on the <style> element will run AFTER the Session service has refreshed in the application's run block... which means the theme will not get updated after pressing F5 because the callback is registered after the initialization of the data occured. I would have to call a manual refresh here to keep it in sync, but if I did that, it may execute twice in the times where the order is different! This is a big problem. I don't think this issue is just related to Firebug... it could happen under any circumstance, but Firebug seems to cause it somewhat consistently, and this is bad.
To recap... This asynchronous ordering is good:
Theme Directive registers callback to Session
Menu Bar application controller registers callback to Session
Session.refresh() is called in .run block.
This asynchronous ordering is bad:
Menu Bar application controller registers callback to Session
Session.refresh() is called in .run block.
Theme Directive registers callback to Session, but callback does not get executed since Session.refresh() was already executed.
So rather than use the observer pattern, or refresh the Session state via a run block, what the best way to design the services, etc. so that the session data will ALWAYS get refreshed after (or maybe before) the various other parts of the application require it? Is there some kind of event I can hook into that gets executed before directives and controllers are executed instead of the run block?
If my approach is generally sound, what can I add to it to really make it work the way it should?
Thanks!
In angular.js you have 2 way of using global variables:
use a $rootScope
use a service
Using $rootScope is very easy as you can simply inject it into any controller and change values in this scope. All global variables have problems!
Services is a singletons(What you need)!
I think in your case you can use
$rootScope
And
$scope.$watch
Great answer
Is there a reason you can't access the variables directly like this:
app.factory('SessionService', function() {
var items = {
"avatar": "some url"
};
return items;
});
var MainController = [$scope, 'SessionService', function($scope, SessionService){
$scope.session = SessionService;
$scope.modifyAvatar = function(url){
$scope.session.avatar = "some new url";
};
}];
var HeaderController = [$scope, 'SessionService', function($scope, SessionService){
$scope.session = SessionService;
// You probably wouldn't do this, you would just bind
// to {{session.avatar}} in your template
$scope.getAvatar = function(){
return $scope.session.avatar;
};
}];

Categories

Resources