I am so annoyed with AngularJS ! I've designed my modules using the following syntax:
angular.module('myModule.controllers').controller('someCtrl',
['$scope', '$route', 'someService', function ($scope, $route, someService) {
someService.getData.success(function(){});
}
And everything used to work fine... until yesterday when I realized that I needed to use resolve in my routes so that I can delay the rendering of my views until all data is returned from my datacontext service and all promised are resolved.
However, that means I have to change the syntax above to:
function someCtrl($scope, $route, someService) {
}
someCtrl.resolve = {
// get data from here
}
someCtrl.$inject = ['$scope', '$route', 'someService'];
So that in my route definition I can do:
controller: someCtrl,
resolve: someCtrl.resolve
I don't like the above syntax. I much preferred what I used to do (the minification-friendly syntax).
Now the problem is, using the new syntax, how do I assign someCtrl to the angular module 'myModule.controllers' that I had defined before ?
I know one way to handle pls see below code i have implemented in my project
Note:If you use module registered controller you have to use literal notation '' with controller name
-->route
$routeProvider.when('/Rally/:date/:id/:month', {
templateUrl: '/partials/RallyDetail.html', controller: 'rallydetailcontroller', resolve: {
rallydata: ['$http', '$route', function ($http, $route) {
return $http({
method: 'GET',
url: 'https://api.mongolab.com/api/1/databases/benisoftlabs/collections/RallyDetail?q={"Candidate":"' + $route.current.params.id + '","Month":"' + $route.current.params.month + '","Date":"' + $route.current.params.date + '"}&apiKey=50920bb9e4b010d72c561d8a'
});
}],
}
});
-->controller
App.controller('rallydetailcontroller',['$scope', 'rallydata', function ($scope, rallydata) {
$scope.rallyData = rallydata.data;
}]);
Related
I am trying to attach notes to $scope instead of controller(this) in the following code:
angular.module('NoteWrangler')
.controller('NotesIndexController', ['$http', function($http) {
var controller = this;
$http({method: 'GET', url: '/notes'}).success(function(data) {
controller.notes = data;
});
}]);
So, when I define $scope like the following :
.controller('NotesIndexController', ['$scope', function($scope)
It doesn't work as I would need to define $http somewhere in order to use it in the code? So, where exactly I should define $scope then?
I have referred this documentation.
You don't "define" $scope, it is a framework object that is managed for you.
If you use the ControllerAs Syntax, your controller can be added to $scope as a property. Otherwise, you would need to refer to the $scope object that is injectable through Angular Dependency Injection. You can inject as many dependencies as you need for your app.
So, the two options which you have available to you are:
ControllerAs:
angular.module('NoteWrangler')
.controller('NotesIndexController', ['$http', function($http) {
var controller = this;
$http({method: 'GET', url: '/notes'}).success(function(data) {
controller.notes = data;
});
}]);
<div ng-controller="NotesIndexController as controller">
{{controller.notes}}
</div>
Direct $scope:
angular.module('NoteWrangler')
.controller('NotesIndexController', ['$scope', '$http', function($scope, $http) {
var controller = this;
$http({method: 'GET', url: '/notes'}).success(function(data) {
$scope.notes = data;
});
}]);
<div ng-controller="NotesIndexController">
{{notes}}
</div>
Note that the $scope object is implicit in the first example and not required in the controller code, and explicit in the second. Also note, $scope has some specific rules regarding primitives and Prototype Inheritance, so it is always recommended to use a dot in your HTML bindings, which the ControllerAs syntax enforces automatically.
Ultimately, the choice of which syntax to use is up to you, but it's recommended to be consistent throughout your application, and either always reference $scope or only reference it for special properties you can't reach any other way.
angular
.module('NoteWrangler')
.controller('NotesIndexController', ['$scope', '$http', function($scope, $http) {
$http({method: 'GET', url: '/notes'}).success(function(data) {
$scope.notes = data;
});
}]);
Not sure why you are using var controller = this; but you have not injected $http
You can use it like
.controller('NotesIndexController', ['$scope', '$http', function($scope, $http){
$http({method: 'GET', url: '/notes'})
.success(function(data) {
$scope.notes = data;
});
}]);
I have multiple clients on my angular app and I want to create different themes inside angular (only the visual part will change, controllers remain the same.
I have a "security" module which manages the authentication, currentLoggedIn user and so on.
var security = angular.module('security', ['ui.router'])
// .factory('authService', authService);
.service('authService', ['$http', '$q', '$window', 'CONSTANTS', '$location', 'currentUser', '$state', '$rootScope', authService])
.factory('authCheck', ['$rootScope', '$state', 'authService', securityAuthorization])
and authService is basically having these methods/values
service.login = _login;
service.logout = _logout;
service.reset = _reset;
service.isAuthenticated = _isAuthenticated;
service.requestCurrentUser = _requestCurrentUser;
service.returnCurrentUser = _returnCurrentUser;
service.hasRoleAccess = _hasRoleAccess;
How can I get access to currentUser inside templateURL function to modify the URL based on data for currentUser?
AuthService and AuthCheck are empty when accessed in templateURL function.
$stateProvider
.state('home', {
url: '/home',
templateUrl: function(authService, authCheck) {
console.log (authService, authCheck);
return 'components/home/home.html'
},
data: {
roles: ['Admin']
},
resolve: {
"authorize": ['authCheck', function(authCheck) {
return authCheck.authorize();
}],
"loadedData": ['metricsFactory', 'campaignFactory', '$q', '$rootScope', 'selectedDates', loadHomeController]
},
controller: 'HomeController',
controllerAs: 'home'
});
In case, we want to do some "magic" before returning the template... we should use templateProvider. Check this Q & A:
Trying to Dynamically set a templateUrl in controller based on constant
Because template:... could be either string or function like this (check the doc:)
$stateProvider
template
html template as a string or a function that returns an html template
as a string which should be used by the uiView directives. This
property takes precedence over templateUrl.
If template is a function, it will be called with the following
parameters:
{array.} - state parameters extracted from the current
$location.path() by applying the current state
template: function(params) {
return "<h1>generated template</h1>"; }
While with templateProvider we can get anything injected e.g. the great improvement in angular $templateRequest. Check this answer and its plunker
templateProvider: function(CONFIG, $templateRequest) {
console.log('in templateUrl ' + CONFIG.codeCampType);
var templateName = 'index5templateB.html';
if (CONFIG.codeCampType === "svcc") {
templateName = 'index5templateA.html';
}
return $templateRequest(templateName);
},
From the documentation:
templateUrl (optional)
path or function that returns a path to an html template that should be used by uiView.
If templateUrl is a function, it will be called with the following parameters:
{array.<object>} - state parameters extracted from the current $location.path() by applying the current state
So, clearly, you can't inject services to the templateUrl function.
But right after, the documentation also says:
templateProvider (optional)
function
Provider function that returns HTML content string.
templateProvider:
function(MyTemplateService, params) {
return MyTemplateService.getTemplate(params.pageId);
}
Which allows doing what you want.
I use routeProvider in Angular JS:
.when('/profile/personal', {
templateUrl: 'personal.html',
controller: 'EditProfileController'
})
How I can pass param to controller EditProfileController and here call Ajax method that returns data. This data must be display in template of route in personal.html.
Example:
.controller('EditProfileController', ['$scope', '$http', function ($scope, $http) {
// If was click on `/profile/personal` from route, must get patam `personal` and call method GetAjax(param);
$scope.GetAjax = function (param){
//here return data put it in template HTML from route
}
}]);
My links are located in page by path:
http://wd.tk/profile
When I click to link route I get URL:
http://wd.tk/profile#/profile/personal/1
Id do:
.controller('EditProfileController', ['$scope', '$http', function ($scope, $http, $routeParams) {
console.log($routeParams);
}]);
I get error:
TypeError: Cannot read property 'idProfile' of undefined
First, in your url configuration, you must put the parameter of url:
when('/profile/personal/:idProfile', {
templateUrl: 'personal.html',
controller: 'EditProfileController'
})
Now, in your EditProfileController, you should get the parameter and call to ajax request:
Inject the $routeParams object and get the parameter with
$routeParams.idProfile:
.controller('EditProfileController',
function ($scope, $http, $routeParams) {
var idProfile = $routeParams.idProfile;
$http.get("service url").then(setData, setError);
function setData(data) {
$scope.data = data;
}
function setError() {
alert("error on get data profile");
}
}]);
In your html, you will show your data profile in the correct format.
But I recommend that all the ajax calls should groups in angular services.
PD:
Check It out angular ui router:
What is the difference between angular-route and angular-ui-router?
hope this helps.
You you need to change your $routeProvider, that should have /profile/:type instead of /profile/personal that means you are going to provide value for :type which can be accessible by injectin $routeParams service inside controller.
.when('/profile/:type', {
templateUrl: 'personal.html',
controller: 'EditProfileController'
})
Controller
.controller('EditProfileController', ['$scope', '$http', '$routeParams', function ($scope, $http, $routeParams) {
$scope.profileType = $routeParams.type;
$scope.GetAjax = function (){
//here you have profile type in $scope.profileType
//you can pass it to ajax by simply accessing scope variable.
$http.get('/getprofiledata?type='+ $scope.profileType)
.success(function(data){
$scope.profileData = data;
})
.error(function(error){
console.log('error occured')
})
}
$scope.GetAjax(); //calling it on controller init
}]);
Update
YOu had missed one of dependency $routeParams in array annotation.
.controller('EditProfileController', ['$scope', '$http', '$routeParams',function ($scope, $http, $routeParams) {
console.log($routeParams);
}]);
I understand how to use Restangular in a controller, however my thoughts are that Restangular is essentially an ORM on steroids.
The ORM shouldn't have any knowledge of the state of the application. That is the job of the controller.
I also want to re-use queries to the ORM, and as such, I believe that Restangular should be used inside a service.
My problem is that I am a js / angularjs and restangular noob, having only about 2-3 months exp with anything front-end.
My Controllers:
app.controller('AdminSupplierIndexController',
['$scope', '$stateParams', '$state', 'Supplier',
function ($scope, $stateParams, $state, Supplier) {
$state.reload();
Supplier.getAll.then(function (suppliers) {
$scope.suppliers = suppliers;
});
}]);
app.controller('AdminSupplierDetailController',
['$scope', '$stateParams', 'Supplier',
function ($scope, $stateParams, Supplier) {
Supplier.getOne({ supplierId : $stateParams.supplierID}).then(function(supplier) {
$scope.supplier = supplier;
});
}]);
My Factory
app.factory('Supplier', ['Restangular', function (Restangular) {
return {
getAll: Restangular.all('supplier').getList(),
getOne: Restangular.one('supplier', supplierId).get()
};
}]);
My Supplier.getAll method works fine - I can list all the suppliers from the Supplier factory.
My problem is with my Supplier.getOne method.
Question 1: How do I inject the supplierId into the factory? I am getting ReferenceError: supplierId is not defined
Question 2: Am I trying to over-engineer things considering that I would have to create individual methods for C-R-U-D for every single factory when these methods are already provided by Restangular?
I know this is old, but an alternate way would just be to wrap it within a function. This way, you can keep any other logic within the service/method.
app.factory('Supplier', ['Restangular', function (Restangular) {
return {
getAll: Restangular.all('supplier').getList(),
getOne: function(supplierId) {
return Restangular.one('supplier', supplierId).get()
}
};
}]);
Found the solution in https://github.com/mgonto/restangular#decoupled-restangular-service
Essentially, the way I have solved this problem is as follows:
app.js
$stateProvider
...
.state('admin.supplier', {
url : "/supplier",
templateUrl : 'templates/admin/supplier/index.html',
controller: "AdminSupplierIndexController",
resolve: {
suppliers: ['Supplier', function(Supplier) {
return Supplier.getList();
}]
}
})
.state('admin.supplier.detail', {
url : "/:supplierId",
templateUrl : "templates/admin/supplier/detail.html",
controller: "AdminSupplierDetailController",
resolve: {
supplier : ['Supplier', '$stateParams', function(Supplier, $stateParams) {
return Supplier.one($stateParams.supplierId).get();
}]
}
})
...
Supplier.js
app.factory('Supplier', ['Restangular', function(Restangular) {
return Restangular.service('supplier');
}]);
SupplierControllers.js
app.controller('AdminSupplierIndexController', ['$scope', '$stateParams', '$state', 'suppliers',
function ($scope, $stateParams, $state, suppliers) {
$state.reload();
$scope.suppliers = suppliers;
}]);
app.controller('AdminSupplierDetailController', ['$scope', 'supplier',
function ($scope, supplier) {
$scope.supplier = supplier;
}]);
i'm facing a problem when trying to use a different syntax for initiating a controller in my script tag.
Why does this work:
function ListCtrl($scope, Projects) {
$scope.projects = Projects;
}
and this not:
myProject.controller('ListCtrl', ['$scope', 'Projects', function ($scope, Projects) {
$scope.projects = Projects;
}]);
Here is the complete plunker http://plnkr.co/edit/Po16QUxmu3M3FqIGqJ3Y?p=preview
Thanks in advance,
- Jan
When using the .controller syntax you also need to change all the routes that used a function reference to use a string reference
Interestingly: using string reference will also work when defining global controller functions, but the current best practice is to use the .controller syntax and avoid global functions.
var myProject = angular.module('project', ['firebase']).
value('fbURL', 'https://angularjs-projects.firebaseio.com/').
factory('Projects', function(angularFireCollection, fbURL) {
return angularFireCollection(fbURL);
}).
config(function($routeProvider) {
$routeProvider.
when('/', {controller:'ListCtrl', templateUrl:'list.html'}).
otherwise({redirectTo:'/'});
});
// function ListCtrl($scope, Projects) {
// $scope.projects = Projects;
// }
// next 3 lines will work
myProject.controller('ListCtrl', ['$scope', 'Projects', function ($scope, Projects) {
$scope.projects = Projects;
}]);