angularJS 1.4.0 Argument 'MainController' is not a function, got undefined - javascript

(function () {
var app = angular.module("Sports", []);
var MainController = function($scope, $http) {
var onUser = function (response) {
obj = JSON.parse(response);
$scope.sport = angular.fromJson(obj);
};
$http.get("/api/SportApi/Get").success(function (response) {
obj = JSON.parse(response);
$scope.sport = angular.fromJson(obj);
});
};
app.controller("MainController", ["$scope", "$http", MainController]);
}());
So yeah, this script is not working, getting the error it can not find the "main controller as function" whats the problem?
EDIT:
the error cause is in this function:
function consoleLog(type) {
var console = $window.console || {},
logFn = console[type] || console.log || noop,
hasApply = false;
// Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
// The reason behind this is that console.log has type "object" in IE8...
try {
hasApply = !!logFn.apply;
} catch (e) {}
if (hasApply) {
return function() {
var args = [];
forEach(arguments, function(arg) {
args.push(formatError(arg));
});
return logFn.apply(console, args); //throws exception
};
}

Fixed you fiddle. Possibly, problem is in immediate function. Also fixed ng-app and response processing
HTML
<div ng-app="Sports">
<div ng-controller="MainController">
<table class="table table-striped table-hover">
<thead>Sport</thead>
<tr ng-repeat="x in sport">
{{sport}}
</tr>
</table>
</div>
</div>
JS
angular
.module("Sports", [])
.controller("MainController", ["$scope", "$http", function($scope, $http) {
$http.get("https://www.googleapis.com/books/v1/volumes?q=isbn:0747532699")
.success(function (response) {
console.log(response);
$scope.sport = response.items;
});
}]);
Update
Plunker version for AngularJS v1.3.x

Order matters :-
app.controller("MainController", MainController);
var MainController = function($scope, $http) {
var onUser = function (response) {
obj = JSON.parse(response);
$scope.sport = angular.fromJson(obj);
};
$http.get("/api/SportApi/Get").success(function (response) {
obj = JSON.parse(response);
$scope.sport = angular.fromJson(obj);
});
};
MainController.$inject = ['$scope','$http'];

Here is Working Fiddle, Its just a basic because I guess you have problem with finding your controller... I hope it helps you
link
(function(){
var app = angular.module("sports",[]);
app.controller("MainController", function($scope){
this.msg = 'Hello World';
});
})();
I guess you have have messed up with closure (Brackets defining self invoking functions in JS. ), which I have corrected.
And do follow definition structure proposed by Angular Docs.

For angularjs v1.4.x the success and error methods are now deprecated
// Simple GET request example :
$http.get('/someUrl').
then(function(response) {
// this callback will be called asynchronously
// when the response is available
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
then() method is the replacement for deprecated method success()
Github Reference link
API Reference link

Related

Can't save http result to scope

I have a json-file defined and I am trying to load in one of my controllers. I am using a factory to fetch the data:
.factory('myService', function($http) {
var all_data = [];
return {
getAllData: function(){
return $http.get('js/data/all_data.json').then(function(data) {
all_data = data;
return all_data ;
});
}
}
})
Later in my controller I call getAllData() in a loadData()-function:
.controller('QuizCtrl',['$scope','$state','$http','myService',function($scope,$state,$http,myService){
// $scope.myData = []; <-- this makes the app freeze and not respond anymore
$scope.loadData = function(){
myService.getAllData().then(function(all_data){
$scope.myData = all_data.data.all_data;
alert($scope.myData);
});
}
$scope.loadData();
$scope.another_var = $scope.myData;
}])
As you can see first of all I am also calling loadData(). While debugging inside the function (see alert()) I can clearly see how the json has been loaded and applied to the $scope.myData variable.
Once I try to assign the variable to another variable (see $scope.another_var) myData is 'undefined'.
What I tried was defining $scope.myData before the $scope.loadData() call (see comment in code). Unfortunately, this simple variable declaration makes my app freeze completely. I have not found the reason for this yet. Also, I am not sure if it is related to my overall problem.
So what have I missed? Why am I not able to store my "http get" result in my controller's $scope?
EDIT: So in my case, I need the data to be there before the current Controller is even used. Would it be a legit option to put all the code which is executed within the controller into the .then-chain of the promise?
It's because your HTTP request is an asyncronous function while the assignment $scope.another_var = $scope.myData; is syncronous.
Basically what's going on is that when your QuizCtrl controller is loaded, it finishes the statement $scope.another_var = $scope.myData; before it finishes the http request of getAllData(). What you've got is a race condition.
If you want to change the value of another_var move it within your async callback:
$scope.loadData = function(){
myService.getAllData().then(function(all_data){
$scope.myData = all_data.data.all_data;
alert($scope.myData);
// because now $scope.myData is available this assignment will work:
$scope.another_var = $scope.myData;
});
}
$scope.loadData();
Hope this helps.
If you need to udpate a different value based on the value that is already on scope, you could observe the value for changes and update accordingly.
here is what you could do.
var app = angular.module("sampleApp", []);
app.controller("sampleController", ["$scope", "sampleService",
function($scope, sampleService) {
sampleService.sampleMethod(1).then(function(value) {
$scope.value = value;
$scope.$digest();
}, function(error) {});
$scope.$watch(function() {
return $scope.value;
}, function(newValue, oldValue) {
//Default Value when the dependant value is not available
newValue = newValue || 0;
$scope.myNewValue = newValue * 10;
});
}
]);
app.service("sampleService", function() {
this.sampleMethod = function(value) {
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
value = value * 2;
resolve(value);
}, 1000);
});
return promise;
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="sampleApp">
<div ng-controller="sampleController">
<div>Value: {{value}}</div>
<div>Cloned Value : {{myNewValue}}
</div>
</div>
</div>
You are missing a promiss $q
take this method for instance:
.factory('myService', function($http,$q) {
var all_data = [];
return {
getAllData: function () {
var d = $q.defer();
$http.get('js/data/all_data.json')
.success(function (response) {
d.resolve(response);
});
return d.promise;
}
}
})

Callback from Angularjs factory

I want to get a callback from a factory. If I understand correctly, the callback should be in the deepest nested function (i.e. under var myResult = $filter('filter')(myData, {id:exnum})[0];, but I get "TypeError: callback is not a function".
My factory calls another factory, gets a value and injects it into a third one for the final result. This final result logs correctly to console, but I cannot callback to the controller.
Any feedback would be appreciated.
angular.module('resourceFetch', [])
.factory('ResourceFetch', ['JsonService', 'UserProgress', '$filter', function(JsonService, UserProgress, $filter) {
var resourceResult = {};
resourceResult.getResource = function(callback){
UserProgress.getProgress(function(exnum, callback) {
JsonService.get(function(data){
var myData = [];
var myData = data.exercises;
var myResult = [];
var myResult = $filter('filter')(myData, {id:exnum})[0];
console.log(myResult) // <- this displays correctly
callback(myResult); // <- "TypeError: callback is not a function"
});
});
//callback(myResult); <- here "myResult is not defined"
};
return resourceResult;
}]);
This is the controller:
myApp.controller('ResourceFetchTest', function($scope, ResourceFetch) {
$scope.myresults = ResourceFetch.getResource(function(obj1){
console.log('obj1 is ' + obj1);
$scope.MyData = obj1;
$scope.MySelectedData = obj1.string1;
});
});
You could use a promise to return the object
Something like:
angular.module('resourceFetch', [])
.factory('ResourceFetch', ['JsonService', 'UserProgress', '$filter','$q', function(JsonService, UserProgress, $filter,$q) {
var resourceResult = {};
resourceResult.getResource = function(){
var defer = $q.defer();
UserProgress.getProgress(function(exnum) {
JsonService.get(function(data){
var myData = [];
var myData = data.exercises;
var myResult = [];
var myResult = $filter('filter')(myData, {id:exnum})[0];
console.log(myResult) // <- this displays correctly
defer.resolve(myResult);
});
});
return defer.promise;
};
return resourceResult;
}]);
and in the controller:
myApp.controller('ResourceFetchTest', function($scope, ResourceFetch) {
$scope.myresults = ResourceFetch.getResource().then(function(obj1){
console.log('obj1 is ' + obj1);
$scope.MyData = obj1;
$scope.MySelectedData = obj1.string1;
});
});
here's the documentation on promises:https://docs.angularjs.org/api/ng/service/$q
Let me know if you have questions I had the simular problem today and fixed it this way
Sorry, my previous answer was not looking at your code properly, your biggest issue here is that you are trying to pass services within services and it makes your code hard to follow.
What you should do is inject all of your services to your controller module and then you can do something along the lines of this.
myApp.controller('ResourceFetchTest', function($scope, ResourceFetch) {
$scope.dataForProgress = "Bind whatever data in needed to get your progress";
$scope.dataForJson = UserProgress.getProgress(dataForProgress);
$scope.myResults = JsonService.get(dataForJson);
});
Depending on what each service does and what it calls it is possible you are also making Async calls in which case I would recommend looking into the $q directive angular provides.

How to pass this.variable to a (Angular)JS function without receiving a syntax error?

This is my AngulsrJS code:
angular.module("UserApp", ["BaseApp"])
.controller("MainCtrl", ["$http", "$window", "$location", "BaseService", function($http, $window, $location, BaseService) {
var self = this;
self.username = $location.path().substr($location.path().lastIndexOf('/') + 1);
self.watch = function(self.username) {
BaseService.watch(self.username, function() {
// more code
});
};
when I run this code, I get an error pointing to line self.watch = function(self.username) { and the error says:
Uncaught SyntaxError: Unexpected token .
Any idea how I can pass self.username as a parameter to the function without getting an error?
Just remove attribute from function definition :
self.watch = function() {
BaseService.watch(self.username, function() {
// more code
});
};
function() {
will still accomplish what you want

Calling function within angular function

I'm trying to convert my $scope code to 'ControllerAs' code and I am having trouble writing a function inside my controller function.
index.html
<html ng-app="main">
<head>
<script src="angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainController as mainCtrl">
{{mainCtrl.message}}
{{mainCtrl.result.username}}
</body>
</html>
script.js
(function() {
angular.module("main", [])
.controller("MainController", ["$http",MainController]);
function MainController($http) {
this.message = "Hello Angular!";
this.result = callFunction($http);
var callFunction = function($http) {
return $http.get("https://api.github.com/users/robconery")
.then(onUserComplete);
};
var onUserComplete = function($response) {
return $response.data;
};
};
}());
Here is the $scope code that I am trying to convert.
(function() {
var app = angular.module("githubViewer", []);
var MainController = function($scope, $http) {
var onUserComplete = function(response) {
$scope.user = response.data;
};
var onError = function(reason) {
$scope.error = "Could not fetch the user";
};
$http.get("https://api.github.com/users/robconery")
.then(onUserComplete, onError);
$scope.message = "Hello, Angular!";
};
app.controller("MainController", ["$scope", "$http", MainController]);
}());
You are invoking callFunction before it is defined. You need to either use a function declaration or move callFunction before the invocation. Here's an example of both of those choices.
Function Declaration
(function() {
angular.module("main", [])
.controller("MainController", ["$http",MainController]);
function MainController($http) {
this.message = "Hello Angular!";
this.result = callFunction($http);
}
function onUserComplete(response) {
return response.data;
}
function callFunction($http) {
return $http.get('https://api.github.com/users/robconery')
.then(onUserComplete);
}
}());
Or:
(function() {
angular.module("main", [])
.controller("MainController", ["$http",MainController]);
var callFunction = function($http) {
return $http.get("https://api.github.com/users/robconery")
.then(onUserComplete);
};
var onUserComplete = function($response) {
return $response.data;
};
function MainController($http) {
this.message = "Hello Angular!";
this.result = callFunction($http);
}
}());
See this excellent StackOverflow answer for the differences between these two syntaxes.
Aside from the function definition problem in #Dan's answer, there is another issue: you should not bind callFunction($http) in the template, callFunction($http) returns a Promise, it doesn't evaluates to the response, even after the onUserComplete callback.
This works for me:
function callFunction($http){
return $http.get("https://api.github.com/users/robconery")
.then(onUserComplete);
}
var that = this;
function onUserComplete($response){
that.result = $response.data;
}
callFunction($http);
EDIT:
Your $scope version code works fine, because in the onUserComplete() function, you assign to $scope.result, not return $response.data. You see, when you return from onUserComplete, then() doesn't return that, it still returns the promise, that's because it needs to support chaining.

Angularjs inject provider into module factory function by string name for minification

I have the following code:
appModule = angular.module('appModule', []);
appModule.factory('sharedApplication', function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
});
This code works perfectly and as expected until I try to minify my javascript and then I get
Error: Unknown provider: eProvider <- e
This is because the $http argument in my factory function has been renamed to 'e' for minification purposes. So how can I manually inform the appModule what to inject by name to avoid minification breaking my code?
Thanks in advance.
Try
appModule.factory('sharedApplication', ['$rootScope','$http',function($rootScope, $http) {
}]);
regards
ng-annotate is also a good library so that the required dependency is injected automatically. You should check it out.
Code sample:
/* ngInject */
appModule.factory('sharedApplication', function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
});
Then you don't have to write:
appModule.factory('sharedApplication', ['$rootScope','$http',
function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
}]);
The more elegant and easier to read approach:
appModule.factory('myFactory', myFactory);
myFactory.$inject = ['$rootScope','$http'];
function myFactory($rootScope, $http) {
...
}

Categories