setting the scope elements after the http call in angularjs - angularjs

I am new to AngularJs. I am calling a http get call to fetch a list of names and I want it as soon as the app loads. Hence I have written the logic to get the list of names in the run function on angularjs. I am using a custom service to fetch the names and calling the function inside the run method.
The code in the service method is as below:
angular.module('myApp')
.service('fetchData', function ($http, $rootScope) {
// AngularJS will instantiate a singleton by calling "new" on this function
this.fetchNames = function() {
$http.get('http://hostname:port/names').success(function (person) {
$rootScope.names = person.names;
});
}
In my app.js, I have the code as below:
angular.module('myApp', ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
})
.run (function($rootScope, fetchData){
//first make an ajax call and fetch all the applicatons for the given BU
fetchData.fetchNames();
});
But by the fetchNames gets the names form the http call, the run method is already executed.
Please let me know where I am going wrong.

In your service you can return the promise and then handle the success in your run function.
angular.module('myApp')
.service('fetchData', function ($http, $rootScope) {
// AngularJS will instantiate a singleton by calling "new" on this function
this.fetchNames = function() {
return $http.get('http://hostname:port/names');
}
Now you can handle the success event in run.
.run (['$rootScope', 'fetchData', function($rootScope, fetchData){
//first make an ajax call and fetch all the applicatons for the given BU
fetchData.fetchNames().success(function (person) {
$rootScope.names = person.names;
);
}]);

Related

Can't call on a function in $scope from inside the $http service in the same controller

I was trying to move one of the function I had in my JS file to inside my Angular controller, since I'm calling on this function from inside the controller and it makes sense to put it there and not go to another file.
I can't seem to make the $http service know of this function (highlighter1)
(function(angular) {
'use strict';
angular.module('myApp', ['ui.bootstrap'])
.controller('Controller', function($scope, $http) {
$scope.highLighter1 = function(side, string, load, callback) {}
$http.get('/comments')
.success(function(response) {
$scope.comments = response;
var allEl=[];
var i;
for (i=0; i<response.length; i++) {
allEl.push(response[i]._id);
}
$http.post('/ranges', {"commentIds":allEl})
.success(function(result){
result.forEach(function(item){
highlighter1(item.dataAction, item.rangyObject, true);
})
})
});
})
})(window.angular);
I'm getting an error in the console that "can't file variable highlighter1", so I'm guessing that I need to somehow register it in a different scope of something like that?
It's not a global or even local function. It's an attribute of $scope. So you need $scope.highLighter1(...).
Also note the capital L. JavaScript is case-sensitive.

Angular JS - service not working

I am using a service to get data from the server using $http.get() method. I am calling the function in the service and then accessing its variable from the controller. But it is not working this way.
The code is below
'use strict';
var mission_vision_mod = angular.module('myApp.mission_vision', ['ngRoute']);
mission_vision_mod.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/mission_vision', {
templateUrl: 'partials/mission_vision/mission_vision.html',
controller: 'mission_visionCtrl'
});
}]);
mission_vision_mod.controller('mission_visionCtrl', ['$scope','getMissionData','$http', function($scope, $http, getMissionData) {
$scope.visiontext = "Here is the content of vision";
getMissionData.getmissiondata();
$scope.missions = getMissionData.missiondata;
$scope.len = $scope.missions.length;
}]);
mission_vision_mod.service('getMissionData', ['$rootScope','$http', function($rootScope, $http){
var missiondata;
function getmissiondata(){
$http.get('m_id.json').success(function(data){
missiondata = data;
});
}
}]);
When i write the$http.get() function in the controller itself, it works. I am new to angular JS.
Try writing your service like this
mission_vision_mod.service('getMissionData', ['$rootScope','$http', function($rootScope, $http){
this.getMissionData=function(){
return $http.get('m_id.json');
}
}]);
Use Service in controller like this:
mission_vision_mod.controller('mission_visionCtrl', ['$scope','getMissionData','$http', function($scope,getMissionData,$http) {
$scope.visiontext = "Here is the content of vision";
getMissionData.getMissionData().success(function(response){
$scope.missions=response;
$scope.len = $scope.missions.length;
}).error(function(errorl){
//handle error here
});
}]);
Also I suggest using a better name for service -'MissionDataService' :)
EDIT- Your sequence of injected service should match sequence of injectable names specified in the array..See my last edit
['$scope','getMissionData','$http',
function($scope, $http, getMissionData
The service names don't match with the variable names.
My advice: stop using this array notation. It clutters the code and is a frequent source of bugs. Use ng-annotate.
That said, your service is not correctly defined. It doesn't have any member function that would allow it to be called. Re-read the documentation of services. Defining services using factory() is easier than defining them using service(), BTW. And the service should return the promise returned by $http. Trying to access the value returned by an asynchronous call right after making the asynchronous call will never work. Read http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
Try:
mission_vision_mod.service('getMissionData', ['$rootScope','$http', function($rootScope, $http){
var missiondata;
function getmissiondata(){
$http.get('m_id.json').success(function(data){
missiondata = data;
return missiondata;
});
}
}]);

Is there a way to hold off rendering the AngularJS view before all the AngularJS $scope data has been retrieved?

This might be a beginner question, but I am retrieving data via http calls in AngularJS and setting them as properties in the $scope variable. However, since http calls take a while, my page tries to load AngularJS more than once in order to render different parts of the page as more the data is retrieved. Is there a way around this? (to hold off on loading the page before all data has been retrieved)
What you could do is to use ng-hide or ng-cloak, so that whatever should not be displayed until the http call fully loaded the data would remain hidden.
take a look at the resolve property in the route settings. If you set something to be resolved the router will resolve this before going to the controller.
app.config(function ($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: "app.html",
controller: "AppCtrl"
resolve: {
app: function ($q, $timeout) {
YourFactory.getData({});
}
}
}
)
});
then create a Factory that will get the data you need
app.factory('YourFactory', ['$http', '$q',
function($http, $q) {
var url = '/api2.php/api';
var YourFactory = {};
var factory_data = [];
var messages = [];
YourFactory.getData = function(params) {
console.log("into GET data");
var deferred = $q.defer();
$http.get(url).success(function(response) {
angular.copy(factory_data, response.data);
deferred.resolve();
}).error(function(response) {
//couldn't resolve therefore it's rejected
deferred.reject();
});
//returns a promise that indicates that something is being resolved and will be returned for the app to continue
return deferred.promise;
};
YourFactory.data = function() {
return factory_data;
};
return YourFactory;
}
]);
then in your controller you need to input the factory and set the scope data from the Factory. Remember that Angular used the Factory to get data before the controller using the resolve property.
app.controller("AppCtrl", ['$scope','YourFactory',
function($scope, YourFactory) {
$scope.data = YourFactory.data();
});
(I haven't tested the code, I simply wrote an example based on an app that I'am doing and in which I passed through the same things as you)
Look at this links if you have any doubt.
https://egghead.io/lessons/angularjs-resolve
http://www.javierlerones.com/2013/07/preloading-data-using-deferred-promises-in-angular-js.html

Angular getting access to $routeParams in a controller not connected to the route

I have a SPA Angular app which has two main html divs. One of these changes frequently and the other less frequently. The frequently changing one uses $route in the app.config. The less frequently changing div also needs to be aware of url changes, so I want to listen for changes in $routeParamas and do stuff accordingly.
So in my controller I have:
.controller('SecondaryCtrl', function ($scope, $routeParams, MyService) {
$scope.$watch('routeParams', function () {
console.log('routeParams: ', $routeParams);
// I need $routeParams.projectId to compose an API call.
});
...
});
In the console, $routeParams is returned as an empty object. I know that if the Controller and route are defined in the app.config, the$routeParams are available, but the app.config already has definition for the given route which links to the PrimaryCtrl:
.config( function ($interpolateProvider, $routeProvider) {
$routeProvider
.when('/project/:projectId', {
templateUrl : 'partials/_project_detail.html',
controller: 'PrimaryCtrl',
resolve: {
project: function ($route, MyService) {
return MyService.get('projects/', $route.current.params.projectId);
},
}
})
So, how can I get access to the $routeParams in my SecondaryCtrl when $routeParams changes?
You can listen to the $routeChangeSuccess event inside of watching $routeParams, like this:
.controller('SecondaryCtrl', function ($scope, MyService) {
$scope.$on('$routeChangeSuccess', function (event, current, previous) {
// current is the current route
// previous is the previous route
});
...
});
Angular Doc

AngularJS Dynamic loading a controller

I read a lot about lazzy loading, but I am facing a problem when using $routeProvider.
My goal is to load a javascript file which contains a controller and add a route to this controller which has been loaded previously.
Content of my javascript file to load
angular.module('demoApp.modules').controller('MouseTestCtrlA', ['$scope', function ($scope) {
console.log("MouseTestCtrlA");
$scope.name = "MouseTestCtrlA";
}]);
This file is not included when angular bootstap is called. It means, I have to load the file and create a route to this controller.
First, I started writing a resolve function which has to load the Javascript file. But declaring my controller parameter in route declaration gave me an error :
'MouseTestCtrlA' is not a function, got undefined
Here is the call I am trying to set :
demoApp.routeProvider.when(module.action, {templateUrl: module.template, controller: module.controller, resolve : {deps: function() /*load JS file*/} });
From what I read, the controller parameter should be a registered controller
controller – {(string|function()=} – Controller fn that should be associated with newly created scope or the name of a registered controller if passed as a string.
So I write a factory which should be able to load my file and then (promise style!) I whould try to declare a new route.
It gave me something like below where dependencies is an array of javascript files' paths to load :
Usage
ScriptLoader.load(module.dependencies).then(function () {
demoApp.routeProvider.when(module.action, {templateUrl: 'my-template', controller: module.controller});
});
Script loader
angular.module('demoApp.services').factory('ScriptLoader', ['$q', '$rootScope', function ($q, $rootScope) {
return {
load: function (dependencies)
{
var deferred = $q.defer();
require(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}
}
}]);
Problem
I still have this javascript error "'MouseTestCtrlA' is not a function, got undefined" which means Angular could not resolved 'MouseTestCtrlA' as a registered controller.
Can anyone help me on this point please ?
Re-reading this article http://ify.io/lazy-loading-in-angularjs/ suggested to keep a $contentProvider instance inside Angular App.
I came up with this code in my app.js
demoApp.config(function ($controllerProvider) {
demoApp.controller = $controllerProvider.register;
});
It enables me to write my controller as expected in a external javascript file :
angular.module("demoApp").controller('MouseTestCtrlA', fn);
Hope this can help !

Resources