I have a directive defined this way:
angular
.module('ui-abc', [ 'xyz'])
.directive('computer', compute);
function compute( item) {
return {
restrict: "EA",
templateUrl: '../elements/src/template.html',
scope:{ qwerty : '=',}
controller: ['$scope','$sce', {
.........
}
The controller does not have a name, how can i add one ? I need this name so that I can refer to that controller inside my ui-router configuration. I tried to do this
function compute( item) {
return {
restrict: "EA",
templateUrl: '../elements/src/template.html',
controller: "controllerName"
}
app.controller("controllerName", function(){......
....
App is not defined in this module, it is defined in the main app.js controller file.
So, it does not work, what do I have wrong?
here, you app will be - var app = angular.module('ui-abc', [ 'xyz']);
And don't use controller: "something", if you don't have one. It'll be fine if you just skip that line.
In your directive you can put a parameter called controllerAs
directive.js
function compute( item) { return {
restrict: "EA",
templateUrl: '../elements/src/template.html',
controller: 'controllerName',
controllerAs: 'vm'
};}
you can now call the controller as vm in your template.html
template.html
<body><h1>{{ vm.variableName }}</h1></body>
You can add the param called 'controllerAs' as below:
function compute( item) {
return {
restrict: "EA",
templateUrl: '../elements/src/template.html',
controller: "controllerName",
controllerAs: 'cName'
};
}
Related
How can I call a function from parent controller inside the child directive?
my controller looks something like this.
angular.module('myVillage')
.controller('myVillageController', myVillageController);
function myVillageController($scope, $q, $element, $timeout) {
function moveHome() {
console.log("moved home")
}
}
my directive looks something like this.
angular
.module('myVillage')
.directive('myVillagModal', myVillagModal);
var vm = this,
cachedKeys = {},
limitInit = 500;
function myVillagModal(myVillage, $filter) {
return {
restrict: 'E',
templateUrl: myVillagelTemplateUrl,
bindToController: true,
scope: {
items: '=',
selectedItems:'=',
selectedItemsChanged: '&'
},
transclude: true,
controller: myVillageController,
controllerAs: 'vm'
};
function myVillageController() {
//....
}
}
I want to call the moveHOme function inside the move-village directive.
<div ng-controller="myVillageController">
<move-village></move-village>
</div>
You can try
$scope.$parent.moveHome();
from the child controller.
Thank you, people, for trying to answer.
I was missing to pass $scope inside the myVillagecontroller due to that I was not able to access parent controller scope.
here is my answer.
angular
.module('myVillage')
.directive('myVillagModal', myVillagModal);
var vm = this,
cachedKeys = {},
limitInit = 500;
function myVillagModal(myVillage, $filter) {
return {
restrict: 'E',
templateUrl: myVillagelTemplateUrl,
bindToController: true,
scope: {
items: '=',
selectedItems:'=',
selectedItemsChanged: '&'
},
transclude: true,
controller: myVillageController,
controllerAs: 'vm'
};
function myVillageController($scope) {
//$scope.$parent now gives the scope of parent controller
//....
$scope.$parent.moveHome(); //this gives 'moved home'
}
}
i have created menu directive like this in app.js.
.directive('menuShow', function () {
return {
restrict: 'EA',
templateUrl: 'shared/menu.html',
}
});
Directive is used in index page as:
<menu-show ></menu-show>
Now, i want to write functionality code which will be used in menu.html directive.
how to write controller for menu.html.
You can create a controller for your directive and set this in directive,
.directive('menuShow', function () {
return {
restrict: 'EA',
templateUrl: 'shared/menu.html',
controller: menuCtrl,
controllerAs: 'test',
bindToController: true
}
});
I have a web app with directives in which the template url is build through a factory, but sometimes I also need the value of one of the attributes, so I do something like this:
myDirective.$inject = ['myFactory'];
function myDirective(myFactory) {
return {
restrict: 'E',
replace: true,
scope: {},
bindToController: {
...
},
controller: myDirectiveController,
templateUrl: function(elem, attrs) {
return angular.isDefined(attrs.myval) ? myFactory.url() : myFactory.altUrl();
}
}
}
Now, I'm changing a few of these to components, and I didnĀ“t manage to do the same, as now components are objects instead of functions.
I can do without using attrs, like this
angular.component('myDirective', {
bindings: {
...
},
controller: 'myDirectiveController as vm',
templateUrl: function(myFactory) {
return myFactory.url();
}
}
but if I try to use also the attrs
angular.component('myDirective', {
bindings: {
...
},
controller: 'myDirectiveController as vm',
templateUrl: function(elem, attrs, myFactory) {
return angular.isDefined(attrs.myval) ? myFactory.url() : myFactory.altUrl();
}
}
I get an angular error. Any idea on how to do this?
This is because with a component, templateUrl became an injectable function:
If templateUrl is a function, then it is injected with the following locals:
$element - Current element
$attrs- Current attributes object for the element
This means you can inject $element and $attrs like any other service, factory, value, etc. you would inject into the templateUrl. This is instead of just receiving the element and attrs as always the first 2 parameters (that can be named anything), like the templateUrl in a directive:
Directive:
templateUrl: function(tElement, tAttrs)
Component:
templateUrl: function(someService, $attrs, $element, someOtherService)
By this logic, in the example you showed above, the error is coming from the fact that angular can't find a service or local with the name elem or attrs.
This is a followed up question from this.
How can I access a property defined in MyController from MyDirectiveController to change its value or just read it and use it for something else? (commented line in the code).
angular
.module("app",[])
.controller('MyController', MyController)
.controller('MyDirectiveController', MyController)
.directive('myDirective', myDirective);
function MyController() {
var vm = this;
vm.foo = 'fooController';
}
function myDirective() {
return {
restrict: 'E',
scope: true,
controller: MyDirectiveController,
controllerAs: 'vm',
template: '{{vmMy.foo}} - {{vm.foo}}'
}
}
function MyDirectiveController() {
var vm = this;
vm.foo = 'fooDirective';
// vmMyfoo = 'fooDirective';
}
Here is the jsfiddle.
You can use bindToController (available from v1.3.x) setting of directive to bind values to controller instance instead of scope object.
function myDirective() {
return {
restrict: 'E',
scope: {
value: '='
},
controller: MyDirectiveController,
controllerAs: 'vm',
bindToController: true,
template: '{{vm.value}} - {{vm.foo}}'
}
}
and in HTML you pass value to directive like this:
<div ng-controller="MyController as vmMy">
<my-directive value="vmMy.foo"></my-directive>
</div>
I have a directive with dynamic controller which is passed via controller-name property.
Directive:
angular
.module('directives.panel', [])
.directive('panel', panel);
panel.$inject = ['$timeout', '$parse'];
function panel($timeout, $parse) {
var directive = {
restrict: 'EA',
transclude: true,
replace: true,
template: '<div class="panel panel-solid panel-table" ng-transclude></div>',
controller: '#',
name: 'controllerName',
controllerAs: 'panel',
link: linkFunc
};
return directive;
}
}
Is it possible to inject resolve 'taskbook' object into dynamic controller?
When I try to do that I get unknown provider. However injecting Resource service (GroupResource) works fine.
Is it possible to inject resolve in directive controller?
State
angular
.module('taskbooks.taskbook', [
'deployment.group',
'resource.deployment',
'resource.taskbook'
])
.config(TaskbookConfig)
.controller('TaskbookController', TaskbookController);
TaskbookConfig.$inject = ['$stateProvider', '$provide'];
function TaskbookConfig($stateProvider) {
$stateProvider
.state('taskbooks.taskbook', {
url: 'taskbooks/:taskbookId',
parent: 'taskbooks',
views: {
"mainContent#taskbooks": {
controller: 'TaskbookController as taskbook',
templateUrl: 'taskbook/taskbook.tpl.html'
}
},
resolve: {
taskbook: TaskbookPrepare
}
});
}
TaskbookPrepare.$inject = ['$stateParams', 'TaskbookResource'];
function TaskbookPrepare($stateParams, TaskbookResource) {
return TaskbookResource.get({
taskbookId: $stateParams.taskbookId
}).$promise;
}
Directive Controller
angular
.module('deployment.groups', ['resource.group'])
.controller('DeploymentGroupController',DeploymentGroupController);
DeploymentGroupController.$inject = ['$scope', '$element', '$attrs', 'GroupResource', 'taskbook'];
function DeploymentGroupController($scope, $element, $attrs, GroupResource, taskbook) {
}
Sort of... If this directive requires the resolve that is associated with this state, then it's safe to assume it will only ever be used in this state, correct?
Going on that idea, the directive can reference the controller set in the state and you can add the resolve to the controller scope.
Here's a very simplified version of what I'm saying...
angular
.module('taskbooks.taskbook')
.config([ $stateProvider, function ($stateProvider) {
$stateProvider
.state('taskbook', {
url: '/:id',
parent: 'taskbooks',
resolve: {
taskbook: [ '$stateParams', 'TaskbookResource', function ($stateParams, TaskbookResource) {
return TaskbookResource.get({
taskbookId: $stateParams.taskbookId
}).$promise;
}]
},
controller: ['taskbook', function (taskbook) {
this.taskbook = taskbook;
}],
controllerAs: 'taskController'
});
}])
.directive('someDirective', function() {
return {
restrict: 'EAC',
controller: 'taskController',
link: function (scope, el, attr, ctrl) {
var taskbook = ctrl.taskbook;
}
}
});
Do note, I removed a lot of the non-relevant code from yours just to get the point across quicker. Obviously this can be reworked into the structure you've written.