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.
Related
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.
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)
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
I have a controller:
app.controller('NavbarController', ['$scope', '$route', function($scope, $route) {
console.log($route);
console.log($route.current)
}]);
But when I try to use $route.current I get undefined, I have no idea why as $route has the propety when I console.log($route)
I have
.when('/', {
templateUrl: '/home',
controller: 'HomeController',
activeTab: 'home'
}).
I need to access $route.current.$$route.activeTab so I can get the variable and set the appropriate class.
Full Controller:
var app = angular.module('PugIt', ['ngRoute', 'ui.bootstrap'])
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/home',
controller: 'HomeController',
activeTab: 'home'
}).
when('/help', {
templateUrl: '/help',
controller: 'HelpController',
activeTab: 'help'
}).
when('/donate', {
templateUrl: '/donate',
controller: 'DonateController',
activeTab: 'donate'
}).
when('/server', {
templateUrl: '/server',
controller: 'ServerController',
activeTab: 'server'
}).
when('/server/new', {
templateUrl: '/server/new',
controller: 'NewServerController',
activeTab: 'serverNew'
}).
otherwise({
redirectTo: '/'
});
});
app.controller('HomeController', ['$scope', '$route', function($scope, $route) {
}]);
app.controller('HelpController', ['$scope', '$route', function($scope, $route) {
}]);
app.controller('DonateController', ['$scope', '$route', function($scope, $route) {
}]);
app.controller('ServerController', ['$scope', '$route', function($scope, $route) {
}]);
app.controller('NewServerController', ['$scope', '$route', function($scope, $route) {
}]);
app.controller('NavbarController', function($scope, $rootScope) {
$route.activeTab = $route.current.$$route.activeTab;
});
Which then sets the active class with:
// Navbar
<div ng-controller="NavbarController">
<li ng-class="{'active': activeTab == 'home'}">Home</li>
</div>
// End of Navbar
<div ng-view></div>
Since you need to keep track of your routes, you can definitely $watch for changes:
.controller('NavbarController', function($scope, $route) {
$scope.$route = $route;
$scope.$watch("$route.current.$$route.activeTab", function(v){
$scope.activeTab = v;
}
});
But this creates an unnecessary $watch. It's not too bad since it is only one, but it would be cleaner to listen to a $routeChangeSuccess event instead:
.controller('NavbarController', function($scope, $route) {
$scope.$route = $route;
$scope.$on("$routeChangeSuccess", function(event, current, previous){
$scope.activeTab = current.$$route.activeTab;
}
});
Most probably the current route is not set when the NavController is loaded.
What you can do in your NavController is to watch over $route.current, and
when it gets set\changed, implement the logic in the watch handler
$scope.$watch(function() {
return $route.current;
},function(newValue,oldValue) {
//implement logic here
});
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.