I'm trying to put the HTTP request in a service file in order to use this function in multiple controllers but I get the error below, I tried multiple solutions but still get this error
here is my controller.js
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/LatestMovies', {
templateUrl: 'LatestMovies/LatestMovies.html',
controller: 'LatestMoviesCtrl'
});
}])
.controller('LatestMoviesCtrl',
['myServices','$scope',function(myServices,$scope) {
$scope.movies = myServices.getLatestMovies();
console.log($scope.movies ,'ggg')
}
]);
here is my services.js
angular.module('myApp', ['ngRoute'])
.factory('myServices', function ($http) {
return {
getLatestMovies : function () {
var service ={
movies : '',
details : []
}
var base = 'http://api.themoviedb.org/3';
var service = '/movie/popular?page=1&language=en-
US&api_key=';
var apiKey = '';
var callback = 'JSON_CALLBACK';
var url =base + service + apiKey + '&callback=' + callback;
//$scope.results = 'requesting...';
$http.jsonp(url).then(function(result, status) {
//$scope.results = JSON.stringify(data);
service.movies = result.data;
angular.forEach(result.data.results, function (value,
index) {
service.details.push(value);
});
},function(result, status) {
service.movies = 'Maybe you missed your API key?' +
JSON.stringify(result.data);
});
return service.movies;
}
}
});
error
angular.js:14199 Error: [$injector:unpr] Unknown provider: myServicesProvider <- myServices <- LatestMoviesCtrl
http://errors.angularjs.org/1.5.11/$injector/unpr?p0=myServicesProvider%20%3C-%20myServices%20%3C-%20LatestMoviesCtrl
at http://localhost:8000/bower_components/angular/angular.js:68:12
at http://localhost:8000/bower_components/angular/angular.js:4563:19
at Object.getService [as get] (http://localhost:8000/bower_components/angular/angular.js:4716:32)
at http://localhost:8000/bower_components/angular/angular.js:4568:45
at getService (http://localhost:8000/bower_components/angular/angular.js:4716:32)
at injectionArgs (http://localhost:8000/bower_components/angular/angular.js:4741:58)
at Object.instantiate (http://localhost:8000/bower_components/angular/angular.js:4783:18)
at $controller
you need to inject the $http module to send api call
.factory('myServices', ['$http',function ($http) {
return {
getLatestMovies : function () {
var service ={
movies : '',
details : []
}
var base = 'http://api.themoviedb.org/3';
var service = '/movie/popular?page=1&language=en-
US&api_key=';
var apiKey = '';
var callback = 'JSON_CALLBACK';
var url =base + service + apiKey + '&callback=' + callback;
//$scope.results = 'requesting...';
$http.jsonp(url).then(function(result, status) {
//$scope.results = JSON.stringify(data);
service.movies = result.data;
angular.forEach(result.data.results, function (value,
index) {
service.details.push(value);
});
},function(result, status) {
service.movies = 'Maybe you missed your API key?' +
JSON.stringify(result.data);
});
return service.movies;
}
}
}]);
It seems like you have been creating myApp module twice, first in services.js and then in controller.js. So basically what happens is
When services.js loaded first, it creates myApp angular module with myServices service.
And when controllers.js file loaded, at the beginning of file you have recreated myApp module using angular.module('myApp', ['ngRoute']). Where it recreate a new myApp module and register config & LatestMoviesCtrl to it.
Hence myServices dependency isn't available.
To fix the issue while registering further files.
angular.module('myApp')
.config(...)
.controller('LatestMoviesCtrl', .... )
Related
I defined a factory that makes a get request but when I inject it in a controller it always throws an undefined error.
This is the factory:
(function() {
'use strict';
var app = angular
.module('myApp');
app.factory('homeFactory', homeFactory);
function homeFactory ($q, $http, $location) {
var data = {};
data.getProducts = getProducts;
function getProducts() {
return $http.get('http://localhost:8000/api/v1/products')
.error(errorMessage);
}
function errorMessage(response) {
console.log('There was an error', response);
}
return data;
}
})();
This is the controller:
(function() {
'use strict';
var app = angular
.module('myApp');
app.controller('homeController', homeController);
homeController.$inject =[homeFactory];
function homeController(homeFactory) {
var home = this;
homeFactory.getProducts()
.success(success);
function success(jsonData, statusCode) {
console.log('The request was successful', statusCode);
console.dir(jsonData);
home.products = jsonData;
}
}
})();
It appears to be ok, but the console throws:
Uncaught ReferenceError: homeFactory is not defined
The problem is in your DI annotation. You should only use strings
homeController.$inject = ['homeFactory'];
See https://docs.angularjs.org/guide/di#-inject-property-annotation
The $inject property is an array of service names to inject.
The controller function supports dependency injection. You don't need to use the $injector directly. Try this:
var app = angular
.module('myApp');
app.controller('homeController', homeController);
function homeController(homeFactory) {
var home = this;
homeFactory.getProducts()
.success(success);
function success(jsonData, statusCode) {
console.log('The request was successful', statusCode);
console.dir(jsonData);
home.products = jsonData;
}
}
The angular runtime will find the homeFactory service, and automatically pass it to your controller function when it's called.
In controller you shall put factory in dependecies
app.controller('homeController', ['homeFactory', '$scope',
function (homeFactory, $scope){
//scope code goes here
}]
);
I'm new to angularjs an i'm trying to create a login form but i'm getting following error :
Cannot read property 'ClearCredentials' of undefined.
I have used some tutorial stuff. But now i started to create an application from scratch. But i'm stuck with the AuthenticationService.js
This is what i have done
app.js
(function(angular) {
angular.module("app.directives", []);
angular.module("app.AuthenticationService", []);
angular.module("app.controllers", []);
angular.module("app", ['ngRoute','ngResource','routes','app.directives','app.controllers',"app.AuthenticationService"]);
}(angular));
controller.js
//LoginController
(function (angular) {
var LoginController = function($scope,$location,AuthenticationService){
var vm = this;
//todo vm.login = login;
(function initController() {
// reset login status
// calling function from AuthenticationService
AuthenticationService.ClearCredentials();
})();
/* TODO: This has not been tested yet
function login(){
vm.dataLoading = true;
// constructor from AuthenticationService
AuthenticationService.Login(vm.username,vm.password, function(response){
//Check if method respons === success
if (response.success) {
// calling function from AuthenticationService
AuthenticationService.SetCredentials(vm.username, vm.password);
$location.path('/');
} else {
// use function from FlashService
// FlashService.Error(response.message);
// vm.dataLoading =false;
}
});
}*/
}
LoginController.$inject = ['$scope','$location'];
angular.module("app.controllers").controller("LoginController", LoginController);
}(angular));
AuthenticationService.js
(function (angular) {
var AuthenticationService = function($http, $cookieStore, $rootScope, $timeout, UserService) {
var service = {};
service.ClearCredentials = ClearCredentials;
function ClearCredentials() {
$rootScope.globals = {};
$cookieStore.remove('globals');
$http.defaults.headers.common.Authorization = 'Basic ';
}
return service;
}
AuthenticationService.$inject = ['$http', '$cookieStore', '$rootScope', '$timeout', 'UserService'];
angular.module("app.AuthenticationService").factory("AuthenticationService", AuthenticationService);
})(angular);
If you have suggestions for this code please let me also know.
You inject two parameters:
LoginController.$inject = ['$scope','$location'];
But then you refer to the third one. Isn't this a problem?
Check if the inline version would work:
angular.module("app.controllers").controller("LoginController", funtion($scope,$location,AuthenticationService){
...
}
If it does, then there is an issue with Angular injection.
I am trying to set up an angular application that will load controllers dynamically according to the route. I am following this tutorial, but I can't get it to work. I also made some small modifications to the tutorial code that suit me, but I don't think they are the problem.
I have put almost all of my code-flow here, so if you want to skip it, the errors are in the last snippets.
Note: I have changed the code snippets as I progressed.
index.html base file (I removed the ng-app and ng-controller parameters, as I realized that I call them manually with RequireJS):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Little Buddha</title>
<link type="text/css" rel="stylesheet" href="assets/libs/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div>
<div ng-view></div>
</div>
<script type="text/javascript" src="assets/libs/requirejs/require.js" data-main="app/main.js"></script>
</body>
</html>
As you can see, I am using RequireJS to load all scripts dynamically. Here's the main.js configuration file:
(I also edited this file, adding angular and ngRoute to the shim config)
require.config({
baseUrl: '',
urlArgs: 'dev=' + new Date().getTime(),
paths: {
'angular' : '/assets/libs/angular/angular.min',
'ngRoute' : '/assets/libs/angular-route/angular-route.min',
'routeResolver' : '/app/routeResolver',
'app' : '/app/app',
'constants' : '/app/global/constants',
'AuthService' : '/app/global/AuthService',
'AppController' : '/app/global/AppController',
},
shim: {
'angular' : {
exports : 'angular',
},
'ngRoute' : {
deps : ['angular'],
},
}
});
require(
[
'ngRoute',
'app',
'routeResolver',
'constants',
'AppController',
'AuthService',
],
function () {
angular.bootstrap(document, ['littleBuddha']);
}
);
routeResolver.js
'use strict';
define([], function () {
var routeResolver = function () {
this.$get = function () {
return this;
};
this.route = function () {
var resolve = function (baseName, path, secure) {
if (!path) path = '';
var routeDef = {};
routeDef.templateUrl = path + baseName + '.html';
routeDef.controller = baseName + 'Controller';
routeDef.secure = (secure) ? secure : false;
routeDef.resolve = {
load: ['$q', '$rootScope', function ($q, $rootScope) {
var dependencies = [path + baseName + 'Controller.js'];
return resolveDependencies($q, $rootScope, dependencies);
}]
};
return routeDef;
},
resolveDependencies = function ($q, $rootScope, dependencies) {
var defer = $q.defer();
require(dependencies, function () {
defer.resolve();
$rootScope.$apply()
});
return defer.promise;
};
return {
resolve: resolve
}
};
};
var servicesApp = angular.module('routeResolverServices', []);
//Must be a provider since it will be injected into module.config()
servicesApp.provider('routeResolver', routeResolver);
});
app.js
'use strict';
define(['routeResolver'], function () {
var app = angular.module('littleBuddha', ['routeResolverServices']);
app.config(['$routeProvider', 'routeResolverProvider', '$controllerProvider',
'$compileProvider', '$filterProvider', '$provide',
function ($routeProvider, routeResolverProvider, $controllerProvider,
$compileProvider, $filterProvider, $provide) {
console.log('test');
app.register =
{
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
var route = routeResolverProvider.route;
$routeProvider
.when('/login', route.resolve('Login', '/app/components/login/'))
.otherwise({ redirectTo: '/login' });
}
]);
return app;
});
And finally, AppController.js:
'use strict';
define(['app'], function (app) {
//This controller retrieves data from the customersService and associates it with the $scope
//The $scope is ultimately bound to the customers view due to convention followed by the routeResolver
app.register.controller('AppController', function ($scope, USER_ROLES, AuthService) {
$scope.currentUser = null;
$scope.userRoles = USER_ROLES;
$scope.isAuthorized = AuthService.isAuthorized;
$scope.setCurrentUser = function (user) {
$scope.currentUser = user;
};
});
return app;
});
EDIT
So, now I have located the problem. In app.js, app.config function is never called, so the register parameters are never applied and the routes are never computed. Actually, that console.log('test') is never printed.
I think its because you are not initializing the route in routeResolver.
Notice in the tutorial they run the routeResolver immediately with their routeConfig. I can not see where you initialize the this.route function.
From the tutorial:
this.route = function (routeConfig) {
var resolve = function (baseName, path, secure) {
if (!path) path = '';
var routeDef = {};
routeDef.templateUrl = routeConfig.getViewsDirectory() + path + baseName + '.html';
routeDef.controller = baseName + 'Controller';
routeDef.secure = (secure) ? secure : false;
routeDef.resolve = {
load: ['$q', '$rootScope', function ($q, $rootScope) {
var dependencies = [routeConfig.getControllersDirectory() + path + baseName + 'Controller.js'];
return resolveDependencies($q, $rootScope, dependencies);
}]
};
return routeDef;
},
resolveDependencies = function ($q, $rootScope, dependencies) {
var defer = $q.defer();
require(dependencies, function () {
defer.resolve();
$rootScope.$apply()
});
return defer.promise;
};
return {
resolve: resolve
}
}(this.routeConfig);
Yours:
this.route = function (routeConfig) {
var resolve = function (baseName, path, secure) {
if (!path) path = '';
var routeDef = {};
routeDef.templateUrl = path + baseName + '.html';
routeDef.controller = baseName + 'Controller';
routeDef.secure = (secure) ? secure : false;
routeDef.resolve = {
load: ['$q', '$rootScope', function ($q, $rootScope) {
var dependencies = [path + baseName + 'Controller.js'];
return resolveDependencies($q, $rootScope, dependencies);
}]
};
return routeDef;
},
resolveDependencies = function ($q, $rootScope, dependencies) {
var defer = $q.defer();
require(dependencies, function () {
defer.resolve();
$rootScope.$apply()
});
return defer.promise;
};
return {
resolve: resolve
}
};
Notice in yours that this function is not executed.
So I think you need to run this function with a routeConfig object to get it defined and working.
EDIT: even if you don't want a routeConfig object (which seems to be your aim) you still need to run the function with no parameter passed.
Last ideas from me:
Sorry I can't be more help. I will try 2 more suggestions and thats me out i'm afraid.
You say app.config is never called. That might be something to do with load order. Try this in your main.js.
require(
[
'ngRoute',
'app',
'routeResolver',
'constants',
'AppController',
'AuthService',
],
function () {
angular.element(document).ready(function() {
angular.bootstrap(document, ['littleBuddha']);
});
}
);
OR, it never gets called because the line
define(['routeResolver'], function () {
Means that it tries to load routeResolver first. If there is some exception in routeResolver then it will fail hitting the function to setup app at all. In which case I would suggest debugging through to see how far you actually get through routeResolver.js on load.
Thats me out of ideas, when i'm stuck like that, i usually start by getting a version working exactly like the demo and then work backwards to what I actually want step by step to see when it stops working.
Good luck, sorry I couldn't be more help.
I'm newer in AngularJS. So I have a simple question, but I can't find answer. I have code:
angular.module('app', ['app.controllers', 'ngRoute']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/users', {templateUrl: '../pages/list.html', controller: 'UserListCtrl'}).
when('/user-details/:login', {templateUrl: '../pages/form.html', controller: 'UserCtrl' /* and here I need to call userDetails(login) from UserCtrl */}).
otherwise({redirectTo: '/users'});;
}
]);
app.controller('UserCtrl', function ($scope, $http, $location) {
$scope.userDetails = function (login) {
$http.get(url + login).success(function (data) {
$scope.user = data[0];
console.log('tst');
}).error(errorCallback);
};
$scope.createUser = function (user) {
$http.post(url, user).success(function (data) {
$location.path('/users');
}).error(errorCallback);
};
});
My problem is: I don't know how to call specific method of controller when routing matches. I need to call method and give to it parameter :login from routing. How to solve this?
Thanks for your answers
If I understand correctly, you are re-using the same controller for two parts of the view (or for two views), one for creating a user and one for fetching the details of the current user.
Since these two aspects are totally different, it is not advisable to use the same controller for both. The controllers should be different and any common or re-usable functionality should be shared through a service.
In any case, code that makes calls to the backend should not be placed inside controllers, but into services. E.g.:
app.service('UserSrv', function ($http) {
var url = '...';
this.userDetails = function (login) {
return $http.get(url + login);
};
this.createUser = function (user) {
return $http.post(url, user);
};
});
app.controller('UserCtrl', function ($scope, UserSrv) {
var login = '...';
var errorCallback = ...;
// Fetch user details upon initialiation
UserSrv.userDetails(login).success(function (data) {
$scope.user = data[0];
}).error(errorCallback);
});
app.controller('NewUserCtrl', function ($location, $scope, UserSrv) {
var errorCallback = ...;
$scope.createUser = function (user) {
UserSrv.createUser(user).success(function (data) {
$location.path('/users');
}).error(errorCallback);
};
});
You could, also, use $routeProvider's resolve property to "preload" the user's details and pass it to the UserCtrl as an argument.
How can I use angular-resources.js to read in a JSON file through a service?
I am working on a very basic Angular app for testing purposes and am just trying to read in data from JSON file right now. I am placing this code in a service so I can more easily swap it out when we move a server based data store.
My App and App.controller declaration are as follows:
'use strict';
// create module for custom directives
var App = angular.module('App', ['jsonService']);
// controller business logic
App.controller('AppCtrl', function AppCtrl($scope, JsonService) {
console.log("marker 1");
if (!$scope.jsonData) {
console.log("marker 2");
JsonService.getData(function (d) {
console.log(d);
$scope.jsonData = d;
$scope.records = d.length;
});
} else {
console.log("I have data already... " + $scope.jsonData);
}
console.log($scope.jsonData);
});
My JsonService is defined as the follow, at the moment:
'use strict';
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource, $filter) {
// define the remote service using Angular's $resource module
var service = $resource('/data/ProcessModeling-Resources.json', {});
var JsonService = {
// calls $resource.query() to retrieve the remote data.
getData : function getData(callback) {
console.log("marker 3");
service.query(function (data) {
console.log("marker 4");
});
}
};
return JsonService;
});
The console output I am getting follows:
marker 1 app.js:8
marker 2 app.js:11
marker 3 services.js:13
undefined app.js:21
TypeError: Object #<Resource> has no method 'push'
at copy (http://127.0.0.1:8000/lib/angular.js:556:21)
at new Resource (http://127.0.0.1:8000/lib/angular-resource.js:330:9)
at http://127.0.0.1:8000/lib/angular-resource.js:386:32
at forEach (http://127.0.0.1:8000/lib/angular.js:117:20)
at http://127.0.0.1:8000/lib/angular-resource.js:385:19
at wrappedCallback (http://127.0.0.1:8000/lib/angular.js:6650:59)
at http://127.0.0.1:8000/lib/angular.js:6687:26
at Object.Scope.$eval (http://127.0.0.1:8000/lib/angular.js:7840:28)
at Object.Scope.$digest (http://127.0.0.1:8000/lib/angular.js:7707:25)
at Object.Scope.$apply (http://127.0.0.1:8000/lib/angular.js:7926:24) angular.js:5582
I'm receiving my error when I attempt to call my service.query(function (data) { }, which (if I'm understanding correctly) should be pulling my JSON file in.
I've been using AngularJS Cats App as an example for pulling data.
I'd follow #pkozlowski's advice and make sure the response is an array. Anyway, here's an example that loads data from a JSON file similar to what you describe in your comments. It uses ngResource and can help you put things together: http://plnkr.co/edit/Ofq7Md8udEnIhAPF1NgL?p=preview
The service
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource) {
return $resource('cats.json',{ }, {
getData: {method:'GET', isArray: false}
});
});
Notice that isArray is set to false.
Your app and controller
var app = angular.module('app', ['jsonService']);
app.controller('ctrl', function($scope, JsonService){
JsonService.getData(function(data){
$scope.name = data.name;
$scope.children = data.children;
});
});
getData is actually not needed since the Resource class gives you some useful convenience methods such a get, you can just do this
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource) {
return $resource('cats.json');
});
app.controller('ctrl', function($scope, JsonService){
JsonService.get(function(data){
$scope.name = data.name;
$scope.children = data.children;
});
});