I have the directive named "student" and the problem is that i m not able to access the methods inside the directive,for instance i have to call the method "setText" in my controller,how do i do it?
angular.module('sampleApp')
.directive('student', ['appConfig', '$filter', function(appConfig, $filter) {
var template = appConfig.DIRECTIVE_BASE_URL +'/demo/student.html';
return {
restrict: 'E',
replace: true,
controller: ['$scope', function($scope) {
$scope.setText = function(a){
if(a.type === 'manual'){
return 'Manually Placed';
} else {
return '';
}
};
}],
scope: {
studentData: '=',
studentName: '='
},
templateUrl: template
};
}]);
You can define setText inside of student directive.
angular.module('sampleApp')
.directive('student', ['appConfig', '$filter', function(appConfig, $filter) {
var template = appConfig.DIRECTIVE_BASE_URL +'/demo/student.html';
const setText = function(a) {
if(a.type === 'manual') {
return 'Manually Placed';
} else {
return '';
}
};
return {
restrict: 'E',
replace: true,
controller: ['$scope', function($scope) {
$scope.setText = setText;
}],
scope: {
studentData: '=',
studentName: '='
},
templateUrl: template
};
}]);
Related
I have a directive Foo in Directive Bar i am trying to call a function in Foo
but it is not working.
http://jsfiddle.net/4d9Lfo95/3/
example fiddle is created.
angular.module('ui', []).directive('uiFoo',
function() {
return {
restrict: 'E',
template: '<p>Foo</p>',
link: function($scope, element, attrs) {
$scope.message = function() {
alert(1);
};
},
controller: function($scope) {
this.message = function() {
alert("Foo Function!");
}
}
};
}
).directive('uiBar',
function() {
return {
restrict: 'E',
template: '<button ng-click="callFunction()">Bar</button> <ui-foo></ui-foo>',
require: 'uiFoo',
scope: true,
link: function($scope, element, attrs, uiFooController) {
$scope.callFunction = function() {
alert('Bar Function');
uiFooController.message();
}
}
};
}
);angular.module('myApp', ['ui']);
where as the UI looks like this
<div ng-app="myApp"> <ui-bar> </ui-bar></div>
You left out this error message:
Controller 'uiFoo', required by directive 'uiBar', can't be found!
The problem is that the require hierarchy searches up the tree, not down it. So, ui-bar is trying to find a uiFoo directive controller either on itself or (with the ^ symbol) in one of it's ancestors, not one of it's children.
If you want to call a method from the child directive, just use the scope: http://jsfiddle.net/4d9Lfo95/5/
angular.module('ui', []).directive('uiFoo',
function() {
return {
restrict: 'E',
template: '<p>Foo</p>',
controller: function($scope) {
$scope.message = function() {
alert("Foo Function!");
}
}
};
}
).directive('uiBar',
function() {
return {
restrict: 'E',
template: '<button ng-click="callFunction()">Bar</button> <ui-foo></ui-foo>',
scope: true,
controller: function($scope) {
$scope.callFunction = function() {
alert('Bar Function');
$scope.message();
}
}
};
}
);
I can not access the vm.screensize property from the relevant controller. The error I am receiving is the vm is not defined. Below are the directive and controller.
angular.module('app.ain.directives')
.directive('ainProjectWizardExplanations', function() {
return {
restrict: 'E',
bindToController: true,
scope : {
sidenavHidden : '='
},
controller: 'ProjectWizardExplanationsController as vm',
templateUrl: function() {
console.log(vm.screensize, vm.animate);
if(vm.screensize) {
return 'app/ain/shared/directives/projectWizardExplanationsMobile.html';
}else {
return 'app/ain/shared/directives/projectWizardExplanations.html';
}
}
};
});
//controller
angular
.module('app.ain.directives')
.controller('ProjectWizardExplanationsController', ProjectWizardExplanationsController);
function ProjectWizardExplanationsController($mdMedia,$scope,$rootScope, $timeout) {
var vm = this;
vm.animate = true;
$scope.$watch(function() { return $mdMedia('sm'); }, function(small) {
vm.screensize = small;
});
}
Try setting the "controllerAs" option when declaring the directive instead.
.directive('ainProjectWizardExplanations', function() {
return {
restrict: 'E',
bindToController: true,
scope : {
sidenavHidden : '='
},
controller: 'ProjectWizardExplanationsController',
controllerAs: 'vm',
templateUrl: function() {
console.log(vm.screensize, vm.animate);
if(vm.screensize) {
return 'app/ain/shared/directives/projectWizardExplanationsMobile.html';
}else {
return 'app/ain/shared/directives/projectWizardExplanations.html';
}
}
};
});
Hope that works for you :)
I have two directives. First is using (including) second.
This is my child directive:
angular.module('myApp')
.directive('radioType', function() {
return {
restrict: 'E',
scope: {
question: '=',
onAnswer: '&'
},
template: [
'<div>{{vm.question.text}}<br/>',
'<div>',
'<button ng-repeat="a in vm.question.answers track by $index" ng-click="onSelected(a)">{{a.text}}</button>',
'</div>',
'<button ng-click="myFunction()">Radio</button>',
'</div>'
].join(''),
controller: ['$scope', function($scope) {
$scope.myFunction = function() {
console.log("hello from radio controller");
$scope.vm.onAnswer();
};
$scope.onSelected = function(question) {
$scope.vm.question.answer = question.text;
console.log(question);
};
}],
controllerAs: 'vm',
bindToController: true
};
});
and this is my main directive:
angular.module('myApp')
.directive('question', function($compile) {
var combo = '<div>COMBO - {{vm.content.text}}</div>';
var radio = [
'<radio-type question="vm.content" onAnswer="vm.onAnswer()"></radio-type>'
].join('');
var input = [
'<input-type question="vm.content"></input-type>',
].join('');
var getTemplate = function(contentType) {
var template = '';
switch (contentType) {
case 'combo':
template = combo;
break;
case 'radio':
template = radio;
break;
case 'input':
template = input;
break;
}
return template;
}
var linker = function(scope, element, attrs) {
scope.$watch('vm.content', function() {
element.html(getTemplate(scope.vm.content.type))
$compile(element.contents())(scope);
});
}
return {
restrict: "E",
link: linker,
scope: {
content: '='
},
controller: ['$scope', function($scope) {
$scope.onAnswer = function() {
console.log("answer");
};
}],
controllerAs: 'vm',
bindToController: true
};
})
Inside child directive I have buttons, when someone clicks on one of them I'd like to call function from main directive.
I've included onAnswer: '&' in my child directive, and I'm assigning function inside main directory template, but I can get this working.
Here is Plunker showing my problem: http://plnkr.co/edit/iWU4L3IJLHtADHBl2dIh?p=preview
Any other advice are welcome.
You have 2 errors on scripts.js.
On line 6 your attribute should not be camelCase:
'<radio-type question="vm.content" on-answer="vm.onAnswer()"></radio-type>'
and on line 46 your function should be inside object vm:
$scope.vm.onAnswer = function() {
Check this plunker: http://plnkr.co/edit/8O7BRjfE3ZWFLrvMkbXB?p=preview
I wan't to program a flexible angular directive with it's properties defined in an own, simple object.
Angular:
contentFactory.directive("listViewDir", function ($compile) {
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link:
return $scope.config.link(scope, element, attrs);
}
}
});
Own Configuration Object:
contentFactory.controller("indexCtrl", function ($scope) {
$scope.config = oLiftTabs;})
var configurations = [{
controller: function ($scope) {
$scope.ButtonClicked = function () {
alert('Button wurde geklickt!');
}
return $scope;
},
link: function (scope, element, attrs){
var template = "... myTemplate ..";
element.html(template);
$compile(element.contents())(scope);
},
}]
While my solution for the controller works well, it doesn't for the link.
Is there a more proper way for my approach? Can I realize access in my encapsulated method to the services (like $compile) without declaring it in the directive declaration?
Is this what you're trying to achieve? You didn't make it clear where you expect this object to live so I've assumed you want it a parent controller. This doesn't feel like a good idea but without knowing more about your use case it's hard to say.
DEMO
html
<body ng-controller="MainCtrl">
<list-view-dir config="config"></list-view-dir>
</body>
js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
$scope.config = {
controller: function ($scope) {
$scope.ButtonClicked = function () {
alert('Button wurde geklickt!');
}
return $scope;
},
link: function (scope, element, attrs){
var template = '<button ng-click="ButtonClicked()" > Alert</button>';
element.html(template);
$compile(element.contents())(scope);
},
};
});
app.directive("listViewDir", function(){
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link: function(scope, element, attrs){
return scope.config.link(scope, element, attrs);
}
};
});
Update
From your comments it sounds like you need to use a factory. Maybe something like this? It feels pretty ugly but it could be what you're looking for.
DEMO2
var app = angular.module('plunker', []);
app.factory('directiveConfigurations', function($compile){
var configurations = {
'listViewDir': {
controller: function ($scope) {
$scope.ButtonClicked = function(){
alert('Button wurde geklickt!');
};
return $scope;
},
link: function (scope, element, attrs){
var template = '<button ng-click="ButtonClicked()" > Alert</button>';
element.html(template);
$compile(element.contents())(scope);
}
}
};
return {
get: get
};
////////////////////////
function get(key){
return configurations[key];
}
});
app.controller('MainCtrl', function($scope, directiveConfigurations) {
$scope.config = directiveConfigurations.get('listViewDir');
});
app.directive("listViewDir", function(){
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link: function(scope, element, attrs){
return scope.config.link(scope, element, attrs);
}
};
});
My app is like this:
angular.module('app', [
// other includes
'ui.bootstrap'
])
in my directive I'm working on :
angular.module('app').directive('DateFields','DatepickerController', ['$timeout', 'DatepickerController', function ($timeout, DatepickerControlle) {
return {
restrict: 'A',
replace: true,
templateUrl: 'path to calendar.html',
scope: {
element: "=",
flowParameterMap: "=?"
},
controller: ['$scope', '$element', '$timeout', function (scope, element, $timeout) {
if (!scope.element)
return;
scope.overlayClick = function (e)
{
scope.isOpen = true;
var input = $(e.currentTarget).next();
$timeout(function () {
$(input).focus();
$DatepickerController.isOpen = true;
});
}
}]
};
}]);
As you can see I'm trying from code change value of datepickers isOpen variable to show datepicker binded to the other dom object.
But all my tries end in "is undefined" error.
Try this in your directive:
scope: {
element: "=",
isOpen: "=",
flowParameterMap: "=?"
},
Now you should be able to chagne isOpen value.