i have one controller and want to create dymanically element.When i create it the element should call the controller function ,but the function is not called
app.controller('AbnTestController', ['$scope','$timeout',function($scope,$timeout) {
..........................
var tree1;
tree1 = [
{
label: 'test1',
id:'1',
type:'t',
}];
return $scope.addnew= function() {
.........
something
};
In my directive ,i create dynamic element;
app.directive('mytree', [
'$timeout', function($timeout) {
return {
restrict: 'E',
controller: function($scope) {
$scope.launch = function (mn) {........something.....}},
template: "<a ng-click='addnew()'>Click</a>",
replace: true,
scope: {
treeData: '=',
onSelect: '&',
initialSelection: '#',
treeControl: '='
}
...........
}}]);
I want to call 'addnew' function from dynamically created element.
Each directive has an isolated scope.
That means that the 'addNew' function is not available in the scope the directives template is in.
To accomplish this you can add the following line to the 'scope' property of your directive definition:
addNew: '&'
This will bind the scope property to the one of original scope (see: https://docs.angularjs.org/guide/directive)
Your directive should look like this:
app.directive('mytree', [
'$timeout', function($timeout) {
return {
restrict: 'E',
controller: function($scope) {
$scope.launch = function (mn) {........something.....}},
template: "<a ng-click='addnew()'>Click</a>",
replace: true,
scope: {
treeData: '=',
onSelect: '&',
initialSelection: '#',
treeControl: '=',
addNew: '&'
}
...........
}}]);
Related
I am creating a custom directive in angularjs, but for some attributes i am receiving undefined value.
function processinfo(ProcessInfoService, $timeout) {
console.log("processInfo directive");
return {
restrict: 'E',
scope: {
start: '=',
end: '=',
uuid: '='
},
templateUrl: 'k2-modules/js/directives/templates/processInfoTemplate.html',
controller: function($scope) {
var self = this;
console.log($scope.uuid); // undefined
console.log($scope.end); // 164982555555
console.log($scope.start); // 0
self.processData = ProcessInfoService.getInfo($scope.start, $scope.end);
}
}
}
<processinfo start="0" end="164982555555" uuid="a57cf6f8"></processinfo>
For uuid I am getting undefined but for end and start values everything is working fine. I don't know why this is happening since syntax is same for all three. Any help will be appreciated
Your mixing directive syntax with component/controller syntax, in directives $scope is called scope (no dollar). Here's the correct syntax to build a angularjs directive:
angular.module('app').directive('myDirective', MyDirective);
MyDirective.$inject = ['$timeout'];
function MyDirective($timeout) {
return {
scope: {
'propBinding1': '<',
'propBinding2': '&'
},
replace: true,
restrict: 'EA',
templateUrl: 'path to html',
link: function link(scope, element, attrs) {
//... do stuff here ...
}
};
}
I'm using angular 1.5 to build a directive that I can use in different situations. I want to be able to pass in data from the controller to the directive as an object. My set up is something like this:
Controller:
function ControllerWrapper($scope, $location, $window){
$scope.depth= 99;
$scope.filter = {filters: [{column: 'stage', values: ['Closed']}]};
}
HTML:
<div ng-controller="ControllerWrapper">
<my-great-directive max-depth="{{depth}}" filters="filter"></my-great-directive>
</div>
Directive return
return {
restrict: 'E',
templateUrl: function(element, attributes) {
return attributes.templateUrl;
},
link: function(scope, element, attributes) {
var obj = scope.$eval(attributes.filters);
var dir = scope.$eval(attributes.dir);
scope.$watch("filters",function(newValue,oldValue) {
if(scope.vm.dir != null){
scope.vm.dir.rows = scope.filterTreeGrid();
}
}, true);
},
controller: DirectiveController,
controllerAs: 'vm',
bindToController: true,
scope: {
maxDepth: '#',
filters: '=?'
}
};
From what I've read the filters: '=' should be enough to pass the data through but I'm getting a null after it tries to resolve it. Any suggestions?
Using Angular 1.6 I am defining an directive like so:
angular
.module('myApp')
.directive('lyEntity', lyEntity);
function lyEntity() {
return {
restrict: 'E',
scope: {
model: '=',
type: '#'
},
controller: 'lyEntityController',
controllerAs: 'vm',
bindToController: true,
templateUrl: function (elem, attrs) {
return 'components/_templates/' + attrs.type + '.html'
}
};
}
But using it in another template like so:
<ly-entity model="vm.entity" type="{{vm.type}}"></ly-entity>
will result in templateURL components/_templates/{{vm.type}}.html
How can I hand over the value of vm.type to be used in my templateUrl function?
Yeah, it can't be done the way you're trying to do it because templateUrl function is called before the attributes are interpolated. One way to achieve this would be using ng-include.
return {
restrict: 'E',
scope: {
type: '#'
},
link: function(scope, element, attrs){
$scope.templateUrl = 'components/_templates/' + attrs.type + '.html';
},
template: '<ng-include src="templateUrl"/>'
};
So, construct the template url in controller, have ng-include as the template and point the src to the constructed template url.
Here's a good article on how to have dynamic templates: https://medium.com/angularjs-meetup-south-london/angular-directives-using-a-dynamic-template-c3fb16d03c6d#.mizywdk6s
Thanks to #Chantu, I found a solution which is working for me:
Directive:
angular
.module('myApp')
.directive('lyEntity', lyEntity);
function lyEntity() {
return {
restrict: 'E',
scope: {
model: '=',
type: '='
},
controller: 'lyEntityController',
controllerAs: 'vm',
bindToController: true,
template: '<ng-include src="templateUrl"/>'
};
}
Controller:
$scope.templateUrl = 'components/_templates/' + vm.type + '.html';
and call it:
<ly-entity model="vm.entity" type="vm.type"></ly-entity>
Problem:
I'm attempting to pass a value from an ng-repeat into a child-directive but when I try to access my passed variable in directive 2 I get "undefined".
Here's an illustration of what I am attempting. Basically directive 1 represents an array of widgets while directive 2 represents a single widget. I am attempting to pass an item from the ng-repeat loop into my child directive.
My Attempt:
Here's a simplified version of my directive 1 template:
<li ng-repeat="item in widgets">
<directive2 item="item"></directive2>
</li>
Here's a simplified version of directive 2:
angular.module('directive2').directive(
['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
templateUrl: 'ext-modules/tile/widgetTemplate.html',
link: function (scope, element, attrs) {
console.log(scope.item); // undefined
}
};
}]);
The ng-repeat on widgets creates two items and I have verified that the data exists. The application works fine and doesn't throw an error but my console.log returns : undefined.
My Question:
How can I pass a value from a directive template's ng-repeat into a child-directive?
here's a fiddle: http://jsfiddle.net/3znEu/112/
Yet another solution proposal:
HTML:
<div ng-controller="MyCtrl">
<directive1></directive1>
</div>
JavaScript:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function ($scope) {
$scope.widgets = [
'a', 'b', 'c', 'd'
];
}])
.directive('directive1', function () {
return {
restrict: 'E',
scope: false,
template:
'<li ng-repeat="item in widgets">' +
'<directive2 item="item"></directive2>' +
'</li>'
}
})
.directive('directive2', ['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
template:
'<div>elem = {{item}}</div>',
link: function (scope, element, attrs) {
console.log(scope.item);
}
}
}]);
Fiddle: http://jsfiddle.net/masa671/dfn75sp3/
It works fine when you put directive2 as directive name, not module:
http://jsfiddle.net/3znEu/113/
'use strict';
var app = angular.module('myApp', [])
.controller('myController', ['$scope', function($scope) {
$scope.greeting = 'Hello World!';
$scope.widgets = ["111","222","333"]
}]);
app.directive('directive1',
['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
template: '<div>{{item}}</div>',
link: function (scope, element, attrs) {
console.log(scope.item); // undefined
}
};
}]);
I have modified your fiddler a bit http://jsfiddle.net/3znEu/115/. Few changes
1. Added a restrict to your directive.
2. Added a template to render the Items (only for testing and demo)
3. Changed items in scope from '#' to '='
angular.module("myApp").directive("directive1", function(){
return {
restrict: 'E',
scope: {
item: "="
},
template: "{{item}}"
}
});
I need some help on how to pass controllers definitions to inner directive nested in outer directive. Please see http://plnkr.co/edit/Om2vKdvEty9euGXJ5qan for a (not)working example.
Is there any way to make angular interpolate what is passed on script.js#46 as item.ctrlName?
How to use controllerAs syntax in inner directive?
1) if you need the inner directive to have the parent controller you can use the require params on the inner directive. Something like this
angular.module('docsTabsExample', [])
.directive('outer', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
templateUrl: '...', // or template
controllerAs: 'outer',
bindToController: true, // This bind the scope with the controller object
controller: function(scope, element, attrs) {
}
}
})
.directive('inner', function() {
return {
require: '^outer',
restrict: 'E',
transclude: true,
scope: {
title: '#'
},
controllerAs: 'inner',
bindToController: true, // This bind the scope with the controller object
templateUrl: '...', // or template
controller: function(scope, element, attrs, tabsCtrl) {
// tabsCtrl and all the methods on the outer directive
},
};
});
2) You have set controller: controller and controller is a empty function, but you can set there a function like i did before and make sure of put the bindToController: true
I found the solution going step down (up ?) with the abstraction. I'm dynamically constructing the whole directive configuration object and then lazy registering it.
See http://plnkr.co/edit/pMsgop6u51zPLqkfWaWT
angular.module('app', ['moduleLazyLoader'])
.controller('mainCtrl', ['$log', function ($log) {
this.list = [
{
name: 'asd',
ctrl: [
'ItemAsdCtrl',
function () {
$log.debug('ItemAsdCtrl');
}
]
},
{
name: 'xyz',
ctrl: [
'ItemXyzCtrl',
function () {
$log.debug('ItemXyzCtrl');
}
]
}
];
}])
.directive('outer', ['factoryLazyLoader', '$log', '$compile', function (factoryLazyLoader, $log, $compile) {
function controller () {}
return {
restrict: 'E',
controller: controller,
controllerAs: 'outer',
bindToController: true,
scope: {
list: '=list'
},
link: function (scope, element, attributes) {
var directives = [];
scope.outer.list = scope.outer.list.map(function (ele, idx) {
var directiveSuffix = ele.ctrl[0];
directiveSuffix[0].toUpperCase();
var directiveName = 'item' + directiveSuffix,
directiveAttrName = directiveName.split(/(?=[A-Z])/).join("-").toLowerCase();
directives.push(directiveAttrName);
factoryLazyLoader.registerDirective([
directiveName,
function () {
return {
restrict: 'E',
replace: true,
controller: ele.ctrl[1],
controllerAs: ele.ctrl[0],
bindToController: true,
template: '<div>{{' + ele.ctrl[0] + ' | json}}</div>',
scope: {
item: '=item'
}
}
}
])
return ele;
});
var tpl = '<div>';
angular.forEach(directives, function (val, idx) {
tpl += '<' + val +' item="outer.list[' + idx + ']">' + '</' + val + '>';
});
tpl += '</div>'
// debugger;
element.replaceWith($compile(tpl)(scope))
}
};
}])