How to separate a component's controller function into a different file? - javascript

I have been searching and searching, and maybe I have been using the wrong terms on my search, but I couldn't find exactly what I was looking for. I am using Angular 1.5 with components.
Say I have a component A:
var module = angular.module('myApp');
module.component('A', {
templateUrl: 'template.html',
controller: function(){}
});
Now this is very simple. I also know that I can do the following, as long as 'myControllerFunction' is in the same file.
var module = angular.module('myApp');
module.component('A', {
templateUrl: 'template.html',
controller: myControllerFunction
});
function myControllerFunction(){}
Now what do I do if I want to have a file only for 'myControllerFunction'? How do I access that function inside that file from within my component?
I know that using Node.js is easy to use exports and require(), but I am not quite familiar what to do using AngularJS.
Any help would be very much appreciated! Thank you!

you can refer the controller from your module like below :
module.component('A', {
templateUrl: 'template.html',
controller: 'YourController'
});
Then in the another file you can define controller with the method.
function() {
'use strict';
angular.module('app').controller('YourController',
YourController);
YourController.$inject = [ '$scope', '$http', '$window',
'$rootScope' ];
function YourController($scope, $http, $window, $rootScope) {
function yourcontrollerfunction() {
}
yourcontrollerfunction();
}
})();
yourcontrollerfunction function will automatically called when controller is loaded. Controller will be loaded when your module is loaded.

Related

AngularJS component with externally hosted templateUrl?

I have an AngularJS application which I am loading as a plug in into another page with a different path. Therefore, my template URLs must be fully qualified in order for them to resolve to the correct file. However, I am receiving Error: $sce:insecurl
Processing of a Resource from Untrusted Source Blocked.
I tried using resourceUrlWhitelist, but this didn't make my error go away, so I thought I would try trustAsResourceUrl. However, I don't know how to combine that with my component's definition.
Here is my component:
angular
.module('synthApp')
.component('foo', {
templateUrl: 'http://example.com/app/components/main.template.html',
controller: MainController
});
function MainController() {
...
}
I tried the following but received an error that $sce is unknown:
angular
.module('synthApp')
.component('foo', ['$sce', {
templateUrl: $sce.trustAsResourceUrl('http://example.com/app/components/main.template.html'),
controller: MainController
}]);
function MainController() {
...
}
What is the proper way to use trustAsResourceUrl in this situation? Thanks.
component accepts a plain object. It cannot be used for DI like directive. .component('foo', ['$sce', { ... }]) isn't a correct syntax for any kind of DI (not just Angular) because it doesn't involve a function where a dependency could be injected.
As explained in this answer, templateUrl can be DI-enabled function.
It should be:
angular
.module('synthApp')
.component('foo', {
templateUrl: ['$sce', function ($sce) {
return $sce.trustAsResourceUrl('http://example.com/app/components/main.template.html');
}],
controller: MainController
});

AngularJS [$injector:unpr] Unknown provider: dataProvider <- data <- PageCtrl

I have seen the other answers and so far nothing has helped me. I get this error with the following code in a file:
angular.module('myApp.page', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/page/:pageId', {
templateUrl: 'page/view.html',
controller: 'PageCtrl',
resolve: {
data: function($q, $http, $routeParams) {
var deferred = $q.defer();
$http({method: 'GET', url: 'http://....' + $routeParams.pageId})
.then(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}
}
})
}])
.controller('PageCtrl', function ($scope, $rootScope, data) {
//do stuff
}
And in the app.js I have this:
angular.module('myApp', [
'ui.bootstrap',
'ngRoute',
'ngTouch',
'ngResource',
'myApp.page'
]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/'});
}]).
config(['$provide', Decorate])
Everything was working correctly and I fetched the data with the HTTP method with no problems, until I started using the Q library and moved the data fetching into the config section. Any tips? None of the other answers seem to work. Thanks in advance!
You issue is due to the fact that you are using ng-controller directive to instantiate the controller PageCtrl which takes a dynamic dependency data which is only created by the router. So when you inject a dynamic dependency via router resolve and having the router instantiate the controller, you do not need to and should not instantiate the controller via ng-controller it will simply fail due to the lack of dependency availability from the injector. router will manage the instantiation of the controller and setting it up for the respective view for you.
So just remove ng-controller from your view also make sure the partial represented by the route is complete enough to represent the view related to the controller functionality. Also i have seen it is a good practice not to start with a partial view with ng-controller and instantiate with route which will help making that partial view more reusable with a different controller. Also while creating a unit test you can easily mock the dynamic dependency and feed it via the $controller service.

Isn't Inline Array Annotation DI compatible with $routeProvider in AngularJS?

My codes looks like this
angular
.module('main', ['ngRoute'])
.config(['$routeProvider',
($routeProvider) ->
$routeProvider
.when '/',
templateUrl: 'homePage/homePage.html'
controller: 'MainCtrl'
])
angular.module('main').controller('MainCtrl',
['$scope' , ($scope) ->
$scope.test = {}])
The browser will compain Error: [ng:areq] Argument 'MainCtrl' is not a function, got Object.
But if I don't use the inline array dependency injection in MainCtrl and rewrite it like this:
angular.module('main').controller('MainCtrl',
($scope) ->
$scope.test = {})
Then everything works well. Does anyone have ideas about this? Thanks!
As the error message is very clear on the fact that issue is not with $routeProvider, You may want to restructure them. Also note that config block must have a function.
First create the module, then register the controller and config:
angular
.module('main', ['ngRoute']);
and then use it or chain through, i.e
angular.module("main", ["ngRoute"]).controller("MainCtrl", [
"$scope"
($scope) ->
return $scope.test = {}
]).config [
"$routeProvider"
($routeProvider) -> //Check this
return $routeProvider.when("/",
templateUrl: "homePage/homePage.html"
controller: "MainCtrl"
)
]
otherwise with the order of the script you have you are trying to create a controller on the app main before even it exists.
Also note that you need to include angular-router script as well.
Demo

AngularJS - Why are dependencies with modules necessary?

Can you tell me why it is recommended to add dependency modules to the creation of a module?
I've tried to run the code without adding the modules TodoApp.controllers and TodoApp.services. Even though I removed them, everything ran perfectly .. (I call a service via those two files)
app.js
// Injects all the needed modules
var TodoApp = angular.module("TodoApp", [
"ngRoute",
"ngResource",
"TodoApp.controllers",
"TodoApp.services"
]).
config(function ($routeProvider) {
$routeProvider.
when('/', { controller: "listCtrl", templateUrl: 'list.html' }).
otherwise({ redirectTo: '/' });
});
Update
Thank you for your response! :)
Unfortunately, those files don't share a common variable:
That was actually the reason why I didn't understand the set of problem. For me, this code gets stored in nowhere. Could it be because of the dot notation in the naming?
controller.js
angular.module('TodoApp.controllers', []).
controller('listCtrl', function ($scope, $location, todoApiService) {
$scope.todos = todoApiService.getMyTodos().query();
});
services.js
angular.module('TodoApp.services', []).
factory('todoApiService', function ($resource) {
var todoApi = {};
todoApi.getMyTodos = function () {
return $resource('/api/todo/:id', { id: '#id' }, { update: { method: 'PUT' } });
};
return todoApi;
});
You do not need to inject controllers & services since they have to be part of a module anyway.
You could have them labeled like so in the other files:
TodoApp.controllers(/* ... */)
TodoApp.services(/* ... */)
They are already attaching themselves to the module because of the TodoApp variable (which in-turn is angular.module('TodoApp').
It looks like you call the module directly each time:
angular.module('TodoApp.controllers', []).
controller('listCtrl', /* etc etc */ );
Each way, you are simply adding more things (in typical dot notation) to your overall Module, and angular understand it's TodoApp since you are starting it with that.
But sometimes you'll see people inject other modules, in a way inheriting the modules controllers / directives / services / etc.
var HelperModule = angular.module('HelperModule', /*...*/);
HelperModule.directive('headerLinks', /*...*/);
HelperModule.factory('BaseFactory', /*...*/);
// etc etc
var TodoApp = angular.module("TodoApp", ["HelperModule"]); // <-- Module injected
// TodoApp now contains all the directives/etc from that module!
Hope that helps!

AngularJS: Error when injecting $modal inside a controller that is nested inside of a directive

We have a custom directive that generates html around a checkbox. This uses transclusion to inject the contents that are passed within it. It looks something like this:
somecheckbox.js
angular.module('namespace.directives')
.directive('someCheckbox', function() {
return {
templateUrl: 'directives/checkbox.html';
restrict: 'E',
transclude: true
}
}]);
directives/checkbox.html
<label class="styling" ng-transclude>
... some other html
</label>
We extensively use modals throughout our application and are in the process of converting everything to bootstrap's angular directive. We've created a controller that handles a particular type of modal that appears sporadically throughout out application:
angular.module('namespace.controllers').controller('LegalModalController',
['$scope', '$modal',
function($scope, $modal) {
$scope.showLegalModal = function(title, legalTextLocation) {
$modal.open({
templateUrl: 'modals/legal.html',
controller: 'sc.LegalModalInstanceController',
resolve: {
modalTitle: function() {
return title;
},
template: function() {
return eulaTextLocation;
}
}
});
};
}]);
Coming back to the directive piece, there is a case where we need to add a link within the checkbox directive that hooks into the legal controller to pop open a modal window. This is what's being done thus far:
<some-checkbox>Click <a href ng-controller="LegalModalController" ng-click="showLegalModal()">here</a> to...</some-checkbox>
The problem that we're encountering is that we have been thoroughly unable to inject $modal into the controller without getting the following error:
Unknown provider: $modalProvider <- $modal
I've looked everywhere, but I haven't found any others who are in this scenario. Does anyone know what could be the potential root of this problem? This linking works in every case where we are not using a directive.
This is the main.js file that starts up the app:
angular.module('namespace.modules.main', ['namespace.core', 'ui.select2', 'ngSanitize', 'ui.sortable', 'infinite-scroll', 'ui.bootstrap']).
config(['$routeProvider', '$locationProvider', '$httpProvider', '$compileProvider',
function($routeProvider, $locationProvider, $httpProvider, $compileProvider) {
routeProvider = $routeProvider;
$locationProvider.html5Mode(true).hashPrefix('!');
$httpProvider.defaults.headers.patch = {};
$httpProvider.defaults.headers.patch['Content-Type'] = 'application/json; charset="UTF-8"';
// Allow telephone hyperlinks
$compileProvider.urlSanitizationWhitelist(/^\s*(https?|mailto|tel):/);
}]).run(
['$rootScope', '$location', '$timeout', '$window', '$route'
function($rootScope, $location, $timeout, $window, $route) {
// set up $rootScope and route provider here
});
I was able to figure it out. The specific page within our application that this was failing on was its own module, and thus didn't have the correct bootstrap ui dependencies. Oops >.< .

Categories

Resources