AngularJS : Using factory inside a controller - javascript

This is my first attempt to use the Angularjs and I'm trying to create a service and use it inside a controller:
var appTest = angular.module("appTest", ["ngRoute"]);
var appTestControllers = angular.module('appTestControllers', []);
appTest.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
$locationProvider.html5Mode(false);
}
]);
appTest.factory("booksApi", function($http){
var _getBooks = function() {
return $http.get('http://localhost/editora-voo/website/books.json');
};
return{
getBooks: _getBooks
};
});
appTest.controller('HomeCtrl', ['$scope', '$http', function($scope, $http, booksApi) {
booksApi.getBooks().success(function(data) {
$scope.books = data;
});
}]);
But it is returning an error: Cannot read property 'getBooks' of undefined

You missed to add booksApi depnedency inside your controller dependency array, You should add it first and then use that inside the function of controller.
Controller
appTest.controller('HomeCtrl', ['$scope', '$http', 'booksApi', //<--missed dependency here
function($scope, $http, booksApi) {
booksApi.getBooks().then(function(response) {
$scope.books = response.data;
});
}]);
Plunkr Here

Related

Avoid a repeated scope variable in different controllers in AngularJS

I've got few controllers working with different templates:
curryApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'table_index.html',
controller: 'CurryListCtrl'
}).
when('/cities/:cityId/', {
templateUrl: 'template-total.html',
controller: 'CurryDetailCtrl'
}).
when('/cities/:cityId/mobile/', {
templateUrl: 'template-mobile.html',
controller: 'CurryMobileCtrl'
}).
when('/cities/:cityId/online/', {
templateUrl: 'template-online.html',
controller: 'CurryOnlineCtrl'
}).
All of theses controllers have $scope variable called cities
For example, the first one:
curryControllers.controller('CurryDesktopCtrl', ['$scope', '$routeParams', '$http', '$route',
function($scope, $routeParams, $http, $route) {
$scope.cityId = $routeParams.cityId;
$http.get('json/cities.json').success(function (data) {
$scope.cities = data;
...
The second one:
curryControllers.controller('CurryOnlineCtrl', ['$scope', '$routeParams', '$http', '$route',
function($scope, $routeParams, $http, $route) {
$scope.cityId = $routeParams.cityId;
$http.get('json/cities.json').success(function(data) {
$scope.cities = data;
...
Is it okay to have repeated $scope variables in different controllers?
How should I refactor the code in order to escape duplicates?
If cities are not going to change for every controller use services like below
Your service should look like below
app.service('myService',function($http,$q){
var cities=null;
this.getCities=function()
{
var deferred = $q.defer()
if(this.cities==null){
$http.get('json/cities.json')
.then((response) => {deferred.resolve(response);cities=response;})
.catch((error) => deferred.reject(error))
}
else { deferred.resolve(cities)}
return deferred.defer
})
});
Use the above service in the controller
app.controller('ctrl',function($scope,myService){
myService.getCities().then(function(data){ $scope.cities = data;})
})
You can create a factory:
.factory('citiesFactory', function($http) {
function getCities(){
// return promise from function
return $http.get("json/cities.json");
}
return {
getCities: getCities
}
});
then in your controller:
curryControllers.controller('CurryDesktopCtrl', ['$scope', '$routeParams', '$http', '$route', 'citiesFactory'
function($scope, $routeParams, $http, $route, citiesFactory) {
$scope.cityId = $routeParams.cityId;
citiesFactory.getCities().then(function(response){
$scope.cities = response.data;
});
...
You should do create a factory like this. Forgive the syntax, but you get the idea.
app.factory('Cities', function ($http) {
return {
'getData': function() {
$http.get('json/cities.json').success(function (data) {
return data;
}
.error(function(error){
return [];
}
}
};
}]);
and in your controller inject the factory and get the data
curryControllers.controller('CurryOnlineCtrl', ['$scope', '$routeParams', '$http', '$route', 'Cities'
function($scope, $routeParams, $http, $route) {
$scope.cityId = $routeParams.cityId;
$scope.cities = Cities.getData();
...
If the cities json is common for all the controllers.
One option would be to move the common object used across controllers into rootscope refer.
Other option would be to store the cities json in the service itself read here.

Use a service in Angular

I got some problem when I'm trying to use an Angular service in the controlleur of my application.
When I'm trying to use function of my service in my controlleur, my console throw me an error :/
var app = angular.module('app', ['ngRoute'])
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider
.when('/login', {
controlleur: 'login',
templateUrl: 'modules/login/login.html'
})
.otherwise({
redirectTo: '/login'
});
}]);
app.service('coreServices', [function () {
this.helloConsole = function () {
console.log("console services");
};
}]);
app.controller('loginController', ['$scope', '$http', '$rootScope', '$location', 'coreServices', LoginController]);
function LoginController($scope, $http, $rootScope, coreServices) {
var vm = this;
vm.helloConsole = coreServices.helloConsole;
vm.helloConsole();
}
angular.js:13708 TypeError: vm.helloConsole is not a function
at new LoginController
I link you this fiddle to show you how I do: https://jsfiddle.net/h8yaxLap/2/
The error throwed is:
angular.js:13708 TypeError: vm.helloConsole is not a function
at new LoginController
Well in your example angular will map $location to coreService in the injected parameters in the function. So I would go for
app.controller('loginController', ['$scope', '$http', '$rootScope', '$location', 'coreServices', LoginController]);
function LoginController($scope, $http, $rootScope, $location, coreServices)
Change service function to return object
app.service('coreServices', function () {
return {
helloConsole: function () {
console.log("console services");
}
};
});
You missed $location parameter for the controller
function LoginController($scope, $http, $rootScope,$location, coreServices)

Routing causing 'w is not afunction'

I get: Error: w is not a function
scripts/app.js
var app = angular.module('app', [
'homepageControllers',
'ngRoute'
]);
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'views/home-page.html',
controller: 'homePageCtrl'
}).
otherwise({
redirectTo: '/homepage'
});
}]);
scripts/controllers/homepageController.js
var homepageControllers = angular.module('homepageControllers', []);
homepageControllers.controller('homePageCtrl', function ($scope, $http) {
console.log("controller loaded");
});
views/home-page.html
<div>
Work ffs!
</div>
index.html
<div ng-view></div>
I'm new to angular and followed this tutorial step-by-step. Google doesn't have the answer, ideas anyone?
This seems like a minifying issue. You should force dependency injections mapping :
Transform this :
scripts/controllers/homepageController.js
var homepageControllers = angular.module('homepageControllers', []);
homepageControllers.controller('homePageCtrl', function ($scope, $http) {
console.log("controller loaded");
});
to this :
scripts/controllers/homepageController.js
var homepageControllers = angular.module('homepageControllers', []);
homepageControllers.controller('homePageCtrl', ['$scope', '$http', function ($scope, $http) {
console.log("controller loaded");
}]);

How does the "main" controller access $routeParams in this example?

I'm experimenting with $routeParams, by following along with this example in the AngularJS documentation. For reference, here is the script itself:
angular.module('ngRouteExample', ['ngRoute'])
.controller('MainController', function($scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
})
.controller('BookController', function($scope, $routeParams) {
$scope.name = "BookController";
$scope.params = $routeParams;
})
.controller('ChapterController', function($scope, $routeParams) {
$scope.name = "ChapterController";
$scope.params = $routeParams;
})
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterController'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
What I can't understand is this: how does MainController get the updated $routeParam object? I can see that as I click, items that MainController is responsible for setting are changing, but I don't understand how. It's making it a little tough to reproduce this behavior.
It doesn't get re-instantiated, and it's not "getting" the updated $routeParams object - the object in the controller is the routeParams object. It is the same object that is in the other controllers, not a "copy" of it.
So when the $routeParams object gets changed, the other controller already has the changes.

Restangular method being fired twice

I have the following example:
var loadUserWidget;
loadUserWidget = function() {
console.log(Restangular.one());
if (!$scope.i) {
$scope.i = 0;
}
console.log($scope.i);
return $scope.i = $scope.i + 1;
};
loadUserWidget()
and I get the following console.log
Object {id: undefined, route: undefined, getRestangularUrl: function, getRequestedUrl: function, addRestangularMethod: function…}
cache_list_controller.js?body=1:276
0 cache_list_controller.js?body=1:280
Object {id: undefined, route: undefined, getRestangularUrl: function, getRequestedUrl: function, addRestangularMethod: function…}
cache_list_controller.js?body=1:276
1 cache_list_controller.js?body=1:280
You can see that the restangular method is being fired twice and i can't seem to identify why.
Update:
Contorller:
bbControllers.controller('CacheListController', [
'$scope', 'Restangular', '$rootScope', 'Snippet', '$modal', '$templateCache', "$window", 'Widget', '$sce', '$location', function($scope, Restangular, $rootScope, Snippet, $modal, $templateCache, $window, Widget, $sce, $location) {
var loadUserWidget;
loadUserWidget = function() {
console.log(Restangular.one());
if (!$scope.i) {
$scope.i = 0;
}
$scope.i = $scope.i + 1;
return console.log($scope.i);
};
return loadUserWidget();
}
]);
app.js
var bbPlnkr = angular.module('BBPlnkr', ['BB', 'restangular', 'ngRoute', 'xeditable', 'ngSanitize']);
bbPlnkr.config(function ($routeProvider, $locationProvider, RestangularProvider) {
$routeProvider
.when('/edit', {
templateUrl: '../assets/index.html',
controller: 'CacheListController',
reloadOnSearch: false
})
.when('/edit/:id', {
templateUrl: '../assets/index.html',
controller: 'CacheListController'
})
.when('/invitation/:url', {
templateUrl: '../assets/invitation-detail.html',
controller: 'InvitationController'
})
.otherwise({
redirectTo: '/edit'
});
$locationProvider.html5Mode(true);
});
When using both the ng-controller directive in the template and declaring routes using $routeProvider there will be two instances of the controller, and they will both fire a Restangular request.
If you do
connsole.log($scope.$id);
You should be seeing two different values since there are two different controllers.
Don't use ng-controller when you are using $routeProvider.

Categories

Resources