Cannot read property of undefined angular factory - javascript

I have issue with Angular factory, I've tried many ways, but it's same..
This is error:
TypeError: Cannot read property 'getSchedule' of undefined
at new <anonymous> (http://127.0.0.1:4767/js/ctrls/main.js:3:19)
at d (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:35:36)
at Object.instantiate (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:35:165)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:67:419
at link (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-route.min.js:7:248)
at N (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:54:372)
at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:47:256)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:46:377
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:48:217
at F (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:52:28) <ng-view class="app-content ng-scope" ng-hide="loading">
I have constructed main app this way:
'use strict';
// Declare chat level module which depends on views, and components
angular.module('BenShowsApp', [
'ngRoute',
'ngResource',
'mobile-angular-ui',
'BenShowsApp.filters',
'BenShowsApp.services',
'BenShowsApp.directives',
'BenShowsApp.controllers'
]).
config(['$routeProvider',
function ($routeProvider) {
$routeProvider
.when('/schedule', {
templateUrl: 'partials/main.html',
controller: 'MainCtrl'
});
}]);
//Initialize individual modules
var services = angular.module('BenShowsApp.services', []);
var factories = angular.module('BenShowsApp.factories', []);
var controllers = angular.module('BenShowsApp.controllers', []);
var filters = angular.module('BenShowsApp.filters', []);
var directives = angular.module('BenShowsApp.directives', []);
and tried use this factory/service
services.factory('tvRage', function($http) {
var tvRage = {};
tvRage.getSchedule = function() {
return $http({
method: 'get',
url: 'http://services.tvrage.com/feeds/fullschedule.php',
params: {
country: 'US',
key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
}).then(function (response) {
return response.data;
});
};
return tvRage;
});
with this controller
controllers.controller('MainCtrl', ['$scope','$http','tvRage',
function ($scope, $http, tvRage) {
tvRage.getSchedule().success(function(data){
var parser = new X2JS();
var x2js = parser.xml_str2json(data);
$scope.request = x2js;
}).error(function(){
alert('nouuu');
});
}
]);
$http works when it's all in controller, but from functional side that request should be in factory I think.

You are returning $q promise from the factory. It does not have the methods success and error they are special functions added by $http in the returned httpPromise (which is just an extension of QPromise).
You can either change your factory to return httpPromise by removing the then chaining:
return $http({
method: 'get',
url: 'http://services.tvrage.com/feeds/fullschedule.php',
params: {
country: 'US',
key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
});
Or chain it in your controller with standard q promise functions then/ catch.
controllers.controller('MainCtrl', ['$scope','$http','tvRage',
function ($scope, $http, tvRage) {
tvRage.getSchedule().then(function(data){
var parser = new X2JS();
var x2js = parser.xml_str2json(data);
$scope.request = x2js;
}).catch(function(){
alert('nouuu');
});
}
]);
But with the specific error you are getting it looks like possibly in your original code your DI list does not match argument list. Re-verify by logging what is tvRage and other arguments injected in the controller. This could easily happen because of argument mismatch in the original code. Ex:-
.controller('MainCtrl', ['$scope','tvRage', function ($scope, $http, tvRage){
//Now tvRage will be undefined and $http will be tvRage.
Working Demo
angular.module('app', []).controller('ctrl', ['$scope', '$http', 'tvRage',
function($scope, $http, tvRage) {
tvRage.getSchedule().success(function(data) {
console.log(data)
}).error(function() {
alert('nouuu');
});
}
]).factory('tvRage', function($http) {
var tvRage = {};
tvRage.getSchedule = function() {
return $http({
method: 'get',
url: 'http://services.tvrage.com/feeds/fullschedule.php',
params: {
country: 'US',
key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
});
};
return tvRage;
});;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
</div>

Related

Angular module adding a Service injection error

First time doing an angular application, combining different tutorials but this is the first time I am trying to inject a service.
I have one of my View's controllers like:
angular.module("myApp.Pages").controller('signupController', ['$scope', '$location', '$timeout', 'authService', function ($scope, $location, $timeout, authService) {
}
however am seeing an error when I look at the Console in Developer Tools:
angular.js:12793 Error: [$injector:unpr] Unknown provider:
authServiceProvider <- authService <- signupController
http://errors.angularjs.org/1.5.0-beta.2/$injector/unpr?p0=authServiceProvider%20%3C-%20authService%20%3C-ignupController
My project structure is:
-Client
-App
-Components
-Services
-authService.js
-myAppCore.js
-Views
-app.js
-appRouting.js
-Scripts (References)
-Theme (Css)
-Index.html
My index.html scripts I add:
<!-- Angular References-->
<script src="References/Angular/angular.js"></script>
<script src="References/Angular/angular-route.js"></script>
<script src="References/Angular/angular-ui-router.min.js"></script>
<!-- End Angular References-->
<!-- my app and dependent modules -->
<script src="App/app.js"></script>
<script src="App/appRouting.js"></script>
<!-- Services -->
<script src="App/Components/Services/authService.js"></script>
<!-- END services-->
<!-- Controllers for your pages-->
<script src="App/Pages/Home/homeController.js"></script>
<script src="App/Pages/ContactUs/contactusController.js"></script>
<script src="App/Pages/Entry/entryController.js"></script>
<script src="App/Pages/Signup/signupController.js"></script>
<!-- End Controllers for the page-->
My app.js
angular.module("myApp", [
// User defined modules
'myApp.Templates', // templates
'myApp.Pages', // Pages
'myApp.Core', // Core
// Angular modules
'ui.router', // state routing
'ngRoute', // angular routing
'angular-loading-bar', //loading bar
'LocalStorageModule', //local browser storage
])
and appRouting.js
angular.module("myApp")
.config(["$stateProvider", function ($stateProvider) {
$stateProvider.state('Home', {
url: '/Home',
templateUrl: 'App/Pages/Home/home.html',
controller: 'homeController'
})
.state('Entry', {
url: '/Entry',
templateUrl: 'App/Pages/Entry/entry.html',
controller: 'entryController'
})
.state('Signup', {
url: '/Signup',
templateUrl: 'App/Pages/Signup/signup.html',
controller: 'signupController'
})
.state('Contactus', {
url: '/Contactus',
templateUrl: 'App/Pages/ContactUs/contactus.html',
controller: 'contactusController'
})
.state("otherwise", {
url: "*path",
templateUrl: "App/Pages/NotFound/notFound.html"
});
}])
.run(["$location", function ($location) {
// Go to state dashboard
$location.url('/Home');
}]);
authService which handles login/register:
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var serviceBase = '<location>';
var authServiceFactory = {};
var _authentication = {
isAuth: false,
userName: ""
};
var _saveRegistration = function (registration) {
_logOut();
return $http.post(serviceBase + 'api/account/register', registration).then(function (response) {
return response;
});
};
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
var _logOut = function () {
localStorageService.remove('authorizationData');
_authentication.isAuth = false;
_authentication.userName = "";
};
var _fillAuthData = function () {
var authData = localStorageService.get('authorizationData');
if (authData) {
_authentication.isAuth = true;
_authentication.userName = authData.userName;
}
}
authServiceFactory.saveRegistration = _saveRegistration;
authServiceFactory.login = _login;
authServiceFactory.logOut = _logOut;
authServiceFactory.fillAuthData = _fillAuthData;
authServiceFactory.authentication = _authentication;
return authServiceFactory;
}]);
myAppPages.js and myAppCore.js are the same just their respective names :
angular.module("myApp.Pages", []);
Edit: Seeing a "app is not defined" reference error in authService
You don't defined var app, so use angular.module("myApp") to define your factory
angular.module("myApp").factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService)
Also you can declare var app = angular.module("myApp") and use app
I simply did not declare:
var app = angular.module(...)
And my service was referencing app when that did not exist.

Can I get Angular variable of one controller in other (variable by $http)

I am new to Angularjs and studied a lot. But I stuck at a point. Google doesn't help me. I have a controller and I have data in $scope.results
app.controller('manage_categories', function($scope, $http, $filter, $window) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
})
now i want to access the same in other without any other $http call. I have done with another call but i don't want this . because i need this in many other controllers.something like this
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
//~ $http({
//~ url: base_url + 'employee/fetchData?table=results',
//~ method: "POST",
//~ }).success(function(data) {
//~ $scope.results = data;
//~ });
})
or any other method. Thanks.
update
I tried this
var myApp = angular.module('myApp',[]);
myApp.factory('results', function() {
return {
name : [{id:21,name:'this is test'}]
};
});
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
})
This is working fine . But not working with $http call .
var myApp = angular.module('myApp',[]);
myApp.factory('results', function($scope,$http) {
$scope.results=[];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
return {
name : results
};
});
update 2
after answers i write it like
var canapp = angular.module('canApp', ["ngRoute", "angularFileUpload"]);
canapp.service('ResultsFactory', ['$http', function($http) {
// http call here
var url=base_url + 'employee/fetchData?table=results';
$http.post(url,data).success(function(data){
this.results = data;
});
}])
call like this
canapp.controller('get_candidates', function($scope, $http, $filter, $timeout, $window, ResultsFactory) {
$scope.check=ResultsFactory.results;
});
but it is not setting the value in template
Use $broadcast to share the data between controllers. Your code will look like this
app.controller('manage_categories', function($scope, $http, $filter, $window, $rootScope) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
$rootScope.$broadcast("results",data);
});
});
app.controller('otherCtrlr', function($scope, $rootScope) {
$rootScope.$on("results", function(event, data){
$scope.results = data;
});
});
But using a service call in the controller is not a best approach. Create a factory and create a method to call your service.
From controller you need to call this method. But to avoid two service calls, you definitely need to use broadcast/emit(depending on data transfer is from parent or child)
There are various possible way of communicating between two controllers. If you just Google share data between controllers angularjs, you may found various links:
Using Services to Share Data Between Controllers
Sharing Data Between Controllers
Share data between AngularJS controllers
Passing data between controllers in Angular JS?
So, in short, possible ways are:
Using Angular Factories (recommended)
Using $rootScope (not recommended)
Using top most controller's scope as root scope
You can do this:
app.factory('ResultsFactory', resultsFactory);
resultsFactory.$inject = ['$http'];
function resultsFactory = function(){
var self = {};
var results = null;
self.getResults = function(){
if(!results){
$http.post(url,data).success(function(data){
results = data;
});
}else{
return results;
}
}
return self;
}
Only the first time that you call to ResultsFactory.getResults() this executes the $http call.
Here's a small fiddle explaining how to share data between controllers.
https://jsfiddle.net/frishi/zxnLwz6d/10/
(Check the browser console to see that both controllers can access data via the service.)
Basically the premise of a service is that it is a singleton that can be used by all the controllers registered on your module.
You want to make that $http call in a service:
.service('myService', ['$http', function($http) {
this.getData = function(){
// Simple GET request example:
return $http({
method: 'GET',
url: 'https://api.github.com/users/mralexgray/repos' // example API
}).then(function successCallback(response) {
return response;
}, function errorCallback(response) {
// return error message
});
}
}])
In your controller:
.controller('Controller2',['$scope','myService',function ($scope,myService) {
$scope.foo = myService.getData();
//resolve the promise:
$scope.foo.then(function(data){
console.log(data);
})
}
])
It is strongly recommended to use separated services as frishi pointed out. This sample is in single file and module just to make it readeable. Following implementation stores the promise and actual request is only made on the initial call to getFoo. The rest will get the response from the in memory promise.
'use strict';
angular.module('foo', [])
.factory('FooResource', function SessionResource($http) {
var fooPromise;
return {
getFoo: function getFoo() {
if(!fooPromise) {
fooPromise = $http.post('employee/fetchData?table=results');
}
return fooPromise;
}
};
})
.controller('FooController', function($scope, FooResource) {
FooResource.getFoo().then(function getFooSuccess(data) {
$scope.results = data;
});
});
I use this angular code with ionic framework
may be its help you..
my factory is..
angular.module('starter.services', [])
.factory('Chats', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [{
id: 0,
name: 'Ben Sparrow',
lastText: 'You on your way?',
face: 'img/ben.png'
}, {
id: 1,
name: 'Max Lynx',
lastText: 'Hey, it\'s me',
face: 'img/max.png'
}, {
id: 2,
name: 'Adam Bradleyson',
lastText: 'I should buy a boat',
face: 'img/adam.jpg'
}, {
id: 3,
name: 'Perry Governor',
lastText: 'Look at my mukluks!',
face: 'img/perry.png'
}, {
id: 4,
name: 'Mike Harrington',
lastText: 'This is wicked good ice cream.',
face: 'img/mike.png'
}];
return {
all: function() {
return chats;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
});
and i use this factory in many controllers
.controller('ChatsCtrl', function($scope, Chats) {
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
in this code factory hit http:// request only one time and i use response on two controllers.
Hope its help you.

Inject controller in $routeProvider resolve method

Following the main answer here, I've tried to do the same, with the exception that my controller is isolated.
I get this:
Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
ReferenceError: myController is not defined
I only get this when the resolve: parameter is present.
How can I work around this one ?
Route config:
.state("my.jobs", {
url: "/my/:jobId",
templateUrl: "Views/my/index.htm",
controller: "myController",
resolve: myController.resolve // the root of all evil here
})
controller:
(function (ng, app) {
"use strict";
var ctrl = app.controller(
"myController",
['$scope', 'job',
function ($scope, job) {
$scope.job = job;
}]);
ctrl.resolve = {
job: function ($q, $stateParams, batchService) {
var deferred = $q.defer();
jobService.loadJob($stateParams.jobId, true)
.then(deferred.resolve, deferred.reject);
},
delay: function ($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
};
})(angular, myApp);
I don't want to make the controller a global function, I like it isolated as it is.
In your case you could create one service, that you can consume inside your resolve function.
app.factory('resolveService', ['$q', '$stateParams', 'batchService','jobService',function($q, $stateParams, batchService,jobService ) {
return {
job: function($q, $stateParams, batchService) {
var deferred = $q.defer();
jobService.loadJob($stateParams.jobId, true).then(deferred.resolve, deferred.reject);
return delay.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
}]);
Then the config code will be
.state("my.jobs", {
url: "/my/:jobId",
templateUrl: "Views/my/index.htm",
controller: "myController",
resolve: {
resolveService: "resolveService" //this resolves to a service
}
});
For more info look at this reference

Creating Dynamic views based on ngRoute and a Restlike API

I have set up a small HTML page with a ngView directive in it, which should update when any of the navigation links are clicked, after calling a Restlike API. This bit seems to work, especially when there's no params to use in the request.
As soon as I try to add a param it fails with the following error:
TypeError: undefined is not a function
at Object.<anonymous> (http://localhost:8080/dashboard/js/factorys.js:11:16)
at Object.invoke (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:3965:17)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:3807:37
at getService (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:3929:39)
at invoke (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:3956:13)
at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:3976:23)
at $get (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:7315:28)
at link (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-route.js:907:26)
at nodeLinkFn (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:6752:13)
at compositeLinkFn (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.js:6146:13) <div class="container ng-scope" ng-view="">
My angular scripts look like this:
controllers.js:
var dashboardControllers = angular.module('dashboardControl',['ngRoute','dashboardFactory']);
dashboardApp.controller('PlayersController', function ($scope, $routeParams, Player) {
$scope.players = Player.findAll();
});
dashboardApp.controller('PlayerDetailsController', function ($scope, $routeParams, Player) {
$scope.playerId = $routeParams.playerId;
$scope.player = Player.get();
});
dashboardApp.controller('OverviewController', function ($scope, $routeParams, Overview) {
$scope.overview = Overview.query();
});
factories.js:
var dashboardFactories = angular.module('dashboardFactory',['ngResource']);
dashboardFactories.factory("Overview", ['$resource',
function ($resource) {
return $resource('webresources/overview/', {}, {
query: {method: 'GET', isArray: false}
});
}]);
dashboardFactories.factory("Player", ['$resource',
function ($scope, $resource) {
return $resource('webresources/player/:playerId', {}, {
findAll: {method: 'GET', isArray: true},
get: {method: 'GET', params: {playerId: $scope.playerId}, isArray: false}
});
}]);
The overview controller work, its the Player Controller I seem to be having the error message for.
I created working example here.
NOTE: It uses UI-Router instead of ngRoute... which I guess is really the right way... but the concept is exactly the same.
Firstly we would define the resoruce "player":
.factory('player', ['$resource', function($resource){
return $resource('player:playerId.json', {}, {
findAll: {method: 'GET', isArray: true},
get: {method: 'GET', isArray: false}
});
}])
Why we used url like this player:playerId.json? Just because of the plunker. We profit here from the parametrized URL template ... which allows in the plunker have player.json for a list and player + playerId +.json for each player.
States definition:
// States
$stateProvider
.state('list', {
url: "/list",
templateUrl: 'tpl.list.html',
controller: 'PlayerListCtrl',
resolve : {
list : ['player', function(player){return player.findAll();}]
}
})
.state('player', {
url: "/player/:playerId",
templateUrl: 'tpl.player.html',
controller: 'PlayerCtrl',
resolve : {
player : ['player', '$stateParams'
, function(player, $stateParams){
return player.get({playerId: $stateParams.playerId});
}]
}
})
The most important part is this:
player : ['player', '$stateParams'
, function(player, $stateParams){
return player.get({playerId: $stateParams.playerId});
}]
Because we are letting angular to inject the $stateParams into our resolve. We then take the playerId parameter and pass that into Templated URL - so it will result in player1.json, player2.json,...
In real life it would url like this 'server/api/resource/:id' - but the logic will be the same.
And these are consuming controllers:
.controller('PlayerListCtrl', ['$scope', 'list', function ($scope, list) {
$scope.list = list;
}])
.controller('PlayerCtrl', ['$scope', 'player', function ($scope, player) {
$scope.player = player;
}])
Check it here

how do i pass scope from controller to service in angularjs?

I have the following controller:
'use strict';
/* Controllers */
angular.module('stocks.controllers', []).
controller('MyCtrl1', ['$scope', '$http', 'stockData', function MyCtrl1 ($scope, $http, stockData) {
$scope.submit = function() {
$scope.info = stockData.query();
console.dir($scope.info);
}
}]);
and i want to pass a bound ng-model that sits in my view called ng-model="symbol_wanted" to the following service...
'use strict';
/* Services */
angular.module('stocks.services', ['ngResource']).factory('stockData', ['$resource',
function($resource){
return $resource('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22YHOO%22)%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json', {}, {
query: {method:'GET', isArray:false}
});
}]);
how do i connect the controller's scope to get passed into the service? thanks!
how do i pass scope from controller to service in angularjs?
You can't inject $scope into services, there is no such thing as a Singleton $scope.
i want to pass a bound ng-model that sits in my view called ng-model="symbol_wanted" to the following service...
You can call the service and pass parameters this way:
.factory('stockData', ['$resource', '$q', function ($resource, $q) {
var factory = {
query: function (value) {
// here you can play with 'value'
var data = $resource('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22YHOO%22)%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json', {}, {
query: {
method: 'GET',
isArray: false
}
});
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
}]);
So we call this service and get a promise back like this:
stockData.query(value) // <-- pass value
.then(function (result) {
$scope.data = result;
}, function (result) {
alert("Error: No data returned");
});
BTW, I'd suggest you use $http.get:
Demo Fiddle
Your ng-model value will automatically become a scope property. So, you can just use this in your controller to get the current value:
$scope.symbol_wanted;
So, let's say that you have a function to handle the click in your controller:
$scope.handleMyClick = function() {
stockData.query($scope.symbol_wanted);
}
You can just use the scoped property.

Categories

Resources