Reputation: 8599
I am new to Angular. I have a simple web page, but the codes for controller are not working. It seems I do not call or inject service "ListLogsFactory" in the controller properly. Please help. Thank you.
My codes include a module, service, and controller that all declared/defined as follows:
var myApp = angular.module("ListLogsModule", []);
myApp.factory('ListLogsFactory', function ($http) {
var thisPageNumber = 1;
var thisPageSize = 10;
var baseUrl = '../Api/LogApi/GetLogsByPage';
var items = {};
$http({
method: 'GET',
url: baseUrl,
data: $.param({ pageNumber: thisPageNumber, pageSize: thisPageSize })
})
.success(function (data, status, headers, config) {
items = data;
console.log(items);
})
.error(function (data, status, headers, config) {
alert('error: ' + status);
});
function getData() {
return items;
}
});
// The error is seen in FireFox and happens in the controller code:
myApp.controllers.ListLogsController = function ($scope, ListLogsFactory) {
$scope.logs = ListLogsFactory.getData(); // NOTE: this line throws error on running with something like "ListLogsFactory" is undefined
}
Upvotes: 1
Views: 204
Reputation: 8599
The following is extended the suggestions from @Eduard Gamonal to make variables/methods of angular service or factory, so it is considered a trick to remember syntax of angular service or factory.
Trick to memorize syntax of "service" or "factory" in Angular
Service is tied with "service" key word; "this" key word to make function instance members public; and "=" to make assignments to "function instance members".
Factory is tied with "factory" key word; "return" keyword to make/return a public object; and ":" to all key/value pairs assignments.
Details.
Service deals with "variables" (or "instance members"), and to make them "public", I use the "this" keyword, and because a service deals with "variables" (or "instance members") to-be-public we use "=" after a "variable" name.
"getLogs" can be treated like a "public variable" or "instance member", and written (in "assignment" meaning) like this.getLogs = function() {...}.
And the whole service is defined with the "service" key word:
<script type="text/javascript">
var myApp = angular.module("ListLogsModule", []);
myApp.service('ListLogsService', function () {
this.getLogs = function () {
var logs = [
{"LogId":5405,"RecordedDate" : "2012-11-19T14:22:02.247", "Event" : "Log On"},
{"LogId":5416,"RecordedDate" : "2012-11-19T14:55:02.247", "Event" : "Log Out"}
];
return logs;
}
});
myApp.controller('ListLogsCtrl', function ($scope, ListLogsService) {
$scope.logs = ListLogsService.getLogs();
});
</script>
Factory deals with a returned "object" and to make them "public", I use the "return" keyword, and because a factory deals with "object" to-look-like-JSON-object I use ":" after each "property" name inside { } of the "return" statement.
"getLogs" can be treated like a property (or key) of the returned JSON object, and is written (in "key/value" pair) like getLogs : function() {...}.
And the whole factory is defined with the "factory" key word:
<script type="text/javascript">
var myApp = angular.module("ListLogsModule", []);
myApp.factory('ListLogsFactory', function () {
return {
getLogs: function () {
return[
{"LogId":5405,"RecordedDate" : "2012-11-19T14:22:02.247", "Event" : "Log On"},
{"LogId":5416,"RecordedDate" : "2012-11-19T14:55:02.247", "Event" : "Log Out"}
];
}
}
});
myApp.controller('ListLogsCtrl', function ($scope, ListLogsFactory) {
$scope.logs = ListLogsFactory.getLogs();
});
</script>
In summary: To memorize syntax of "service" or "factory" in Angular
Service is tied with "service" key word; "this" key word to make function instance members public; and "=" to make assignments to "function instance members".
Factory is tied with "factory" key word; "return" keyword to make/return a public object; and ":" to all key/value pairs assignments.
Upvotes: 1
Reputation: 8031
When you use factory
you have to return something. You're just defining a bunch of methods there but they aren't available to anybody.
It's also good to use a different naming convention. For example, instead of LogsController, use LogsCtrl. AngularJS appends "Controller" internally and you might end up, in exotic situations, handling names like "LogsControllerController".
A simplified approach of using factory and returning the service:
var ListLogsModule = angular.module("myApp", []);
ListLogsModule.factory('ListLogsSrv', function ($http) {
// first define the service (you're using a factory)
var getData = function() {
return "hey";//items;
};
// then return it.
// offer a public method "getData" that uses your internal getData()
return {
getData : getData
}
});
ListLogsModule.controller("ListLogsCtrl", function ($scope, ListLogsSrv) {
$scope.w = "world";
$scope.logs = ListLogsSrv.getData();
});
You also have an $http
request in the factory. That means that you'll trigger the async request when you instantiate the service (when it is used for the first time), so nobody will wait for it to finish and you'll be getting undefined
.
If you are using this service in a controller, you will probably need to resolve
a promise.
An example of using a promise:
var promise = $q.defer();
var thisPageNumber = 1;
...
var baseUrl = '../Api/LogApi/GetLogsByPage';
...
promise = $http.get(...
Now you can use this promise in the controller, for example, or in the methods of your service.
I answered a related question two days ago Angular Service Definition: service or factory
Upvotes: 3
Reputation: 40337
myApp.controllers.ListLogsController = function ($scope, ListLogsFactory) {
$scope.logs = ListLogsFactory.getData();
}
should be
myApp.controller("ListLogsController", function ($scope, ListLogsFactory) {
$scope.logs = ListLogsFactory.getData();
});
Upvotes: 1