Angular dependency injection. what the hell am i doing wrong? - angularjs

Here's a simple example of what i'm trying to do. I'll preface this by saying that i have been working as a maintainer for 3 weeks on an already built project in angular, and i have a minor, at best understanding of angular to date. i can work with the controllers and views and models, all that is fine. but when it comes time to understanding the dependency injection, i am stymied by vague errors. Now it's came time i need to learn about how the Injector works, so here's a small test app i have constructed for my own learning purposes. i do not actually know if this is the correct way to build an angular app at all. The documentation i find confusing at best.
html
<div ng-app="app">
<div ng-controller="EC as e">
</div>
</div>
javascript
var app = angular.module('app',[]);
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q, $window) {
return {
'request': function(config) {
config.headers['Authorization'] = 'bearer '+ $window.localStorage.token;
return config;
}
};
});
}]);
function EC($scope,$http,$window) {
var vm = this;
vm.api = function( resource ){
return ('https://api.website.com/v1/'+resource).replace('//','/');
};
$window.localStorage.token = 'foobar';
$http.put( vm.api('/users/me'), { loggedIn: true }).then(function(response){
$http.get( vm.api('/users/me') ).then.function(response){
vm.user = response.data;
});
});
}
EC.$inject = ['$scope','$http','$window'];
app.controller('EC',EC);
app.run();
I had assumed the line EC.$inject = ['$scope','$http','$window']; would insure that my controllers constructor would be called with those services, or whatever the hell they are called, as arguments. Apparently thats not the case. Can someone explain to me like i'm 5 how this works, and why i'm getting an error?
Error message:
Error: [$injector:modulerr] http://errors.angularjs.org/1.5.6/$injector/modulerr

It's just bad markup. Fiddle showing you working code
Change:
.then
.function(response) {
vm.user = response.data;
to
.then(function(response) {
vm.user = response.data;

Rewrote the controller block to follow more conventionaly injection. Might workout for ya. Also removed the double response callback from the $http calls and returned the $http.get() promise.
angular.module('app', [])
.config(['$httpProvider', function($httpProvider)
{
$httpProvider.interceptors.push(function($window)
{
return {
request: function(config)
{
config.headers['Authorization'] = 'bearer '+ $window.localStorage.token;
return config;
}
};
});
}])
.controller('EC', ['$scope', '$http', '$window', function($scope, $http, $window)
{
var buildApiString = function(resource)
{
return ('https://api.website.com/v1/'+resource).replace('//','/');
};
$window.localStorage.token = 'foobar';
$http.put(buildApiString('/users/me'), { loggedIn: true }).then(function()
{
return $http.get(buildApiString('/users/me')).then(function(response)
{
$scope.user = response.data
});
});
}]);

Related

how to reload a partial view on success of a function that is defined in factory

I want to reload a webpage on success of a function. I'd like not to loose the cookie data upon reload too. I don't know how to achieve this as I have defined the function using factory in my controller.
JavaScript Code
'use strict';
angular.module('employees', ['ngTable']);
//Routers
//Factories
myApp.factory('employeeServices', ['$http', function($http) {
var factoryDefinitions = {
moveToBench: function(employeeId) {
return $http.post(myApp.IndecommBaseUrl + '/Workflow?entityId=' + employeeId + '&nextStateId=' + myApp.state.bench)
.success(function(data) {
$route.reload();
});
}
}
return factoryDefinitions;
}]);
//Controllers
myApp.controller('getEmployeesController', ['$scope', 'employeeServices', 'dataTable', function($scope, employeeServices, dataTable) {
employeeServices.getEmployees().then(function(result) {
$scope.data = result.data;
if (!result.data.error) {
dataTable.render($scope, '', "employeesList", result.data);
}
$scope.moveToBench = function(id) {
employeeServices.moveToBench(id);
}
});
}]);
I want the refresh to happen on success of the function 'moveToBench'.
How can I achieve this?
Thanks in advance...
Is the reload not working? Or the factory is not even called? Anyway, This is how I do my reloads:
$window.location.reload();
Give it a try to see if it works =)

AngularJS - Factory - TypeError: Cannot read property 'getSpec' of undefined

I am starting with AngularJS and i am having some issues when trying to use a factory from a controller.
I have the following factory
angular.module('testingApp')
.factory('factoryService', function ($http) {
// Service logic
var getSpec = function(p) {
return $http.get('http://someurl//?p=' + p);
};
return {
getSpec: getSpec
};
});
and then i try to consume it from the controller as follows
angular.module('testingApp')
.controller('ServiceincientsCtrl',[ function (factoryService,$scope) {
console.log('Starting Service Incident Controller');
factoryService.getSpec('AAA').then(function(response){
$scope.result = response.data;
}, function(error){
console.log('opsssss' + error);
});
}]);
But when i try to run it i receive the following message
TypeError: Cannot read property 'getSpec' of undefined
I don't know what i am missing,It should be a newbbie error, I googled it and i tried many examples with the same result.
Any ideas of what i am doing wrong?
Thanks!
Looks like you are not using the dependancy array notation properly. Please refer the below code. Please add 'factoryService' & '$scope' as array items.
.controller('ServiceincientsCtrl', ['factoryService', '$scope', function(factoryService, $scope) {
console.log('Starting Service Incident Controller');
factoryService.getSpec('AAA').then(function(response) {
$scope.result = response.data;
}, function(error) {
console.log('opsssss' + error);
});
}]);
Angular documentaion on dependancy injection.
First of all, you didn't declare your controller properly. It should look like this:
.controller('ServiceincientsCtrl',['$scope', 'factoryService', function($scope, factoryService) {
I personally use Services as I find them more readable.
Here's what your factory would look like as a Service:
myApp.service('factoryService', function ($http) {
this.getSpec = function(p) {
return $http.get('http://someurl//?p=' + p);
}
});
This would work with your current controller.

service not returning value

I have been working to write a service to return username.
var username, $promise;
angular.module('TestApp').factory('UserService', function($http) {
$promise= $http.get('/api/getuser')
.success(function(data) {
username = data;
});
$promise.then(function() {
return username;
});
});
But injecting this service in an controller would return in an undefined value
angular.module('TestApp')
.controller('UserLoginController', function($scope, UserService){
console.log("Username is: "+ UserService);
});
I have confirmed that http get request returns valid username value. I am quite new to angular and would really appreciate if anyone can point out what am I doing wrong here.
This code above looks like spaghetti. Here is a basic factory that should do what you want:
app.factory('UserService', [ '$http', function($http){
var userService = {};
userService.getUser = function(){
return $http.get('/api/getuser').then(function(res){
return res.data;
},function(error){
console.log(error);
return [];
});
}
return userService;
}]);
then call it in a controller:
app.controller('MyController', ['$scope', 'UserService', function($scope,UserService){
$scope.user = {};
UserService.getUser().then(function(data){
$scope.user = data.users[0];
});
}]);
This assumes a json format similar to { users: [{ id: "34534534",name: "John" }] } returned by your API.
Please note that I wrote this on the fly and didn't try it out. It should work though.
Warning: I just edited my code to fix some mistakes.

AngularJS factory not working

I have abstracted my working code from a controller into a factory, but it doesn't seem to be working and I can't find what's wrong. I opted for a factory rather than a service because I wanted to execute some code that defined the variable before returning that variable; I want to get result.station (a part of the data returned by the API), not the full result.
This is my code:
var app = angular.module("myApp", []);
app.factory('api', ['$http',
function($http) {
var station_list = [];
$http({
method: 'GET',
url: 'http://api.irail.be/stations/?format=json&lang=nl'
})
.success(function(result) {
station_list = result.station;
});
return {
Stations: function() {
return station_list;
}
};
}
]);
app.controller("myController", ['api', '$scope',
function(api, $scope) {
$scope.station_list = api.Stations();
$scope.title = "Stations";
}
]);
and a working example.
Try this:
.success(function(result) {
angular.copy(result.station, station_list);
});
You had a small error, you were replacing the array instead of populating it. I used angular.copy instead of the assignment in your factory and it works
http://plnkr.co/edit/sqgKcFZAcClmkfdXHhrz
The problem is that you are dealing with asynchronous nature of AJAX.
I would suggest to have a delegate method in controller, which will be called when the service call is complete.
Something like the following:
app.controller("myController", ['api', '$scope',
function(api, $scope) {
api.Stations( function(station_list) {
$scope.station_list = station_list;
});
$scope.title = "Stations";
}
]);
The following is a service method excerpt:
return {
Stations: function(delegate) {
if (delegate)
delegate(station_list);
return station_list;
}
};

angular js force.com Javascript remoting

I am new to Angular JS and really struggling to get data into my controller from javascript remoting. Has anyone done this before?
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Forecasting.Users}',
new Object(),function(result, event){
return result
}
);
How on earth do i get the data into the controller :
var forecastingCtrl = function($scope, $q){
$scope.lengths = function(){return '5'};
$scope.users = [];
}
EDIT : Following works fine:
fc.service('Users', function($rootScope, $q) {
this.get = function(){
var deferred = $q.defer();
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Forecasting.Users}',new Object(),function(result, event){
if(event) {
$rootScope.$apply(function() {
deferred.resolve(result);
});
} else {
deferred.reject(result);
}
});
return deferred.promise;
}
});
function forecastingCtrl($scope, $q, Users){
$scope.lengths = function(){return '5'};
var promise = Users.get();
promise.then(
function(users){
$scope.users = users;
},
function(reason){
alert('Failed: ' + reason);
}
);
};
I haven't used javascript remoting (sounds interesting) but what you will probably want to do is to encapsulate your visualforce code inside a service, having a method (most likely a promise) to return your data and inject the service into your controller. The upside of this is that you can unit test your controller by injecting a mock or spy of your data service. The pattern would be very much like how you would use angular's $http and $resource services. Hopefully this gets you on the right track.

Resources