Cannot handover attrs.value to Directive's templateUrl function - javascript

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>

Related

Attribute undefined in custom directive in angularjs

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 ...
}
};
}

Angular Passing data to directive through controller

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?

Angular directive > Dynamic controller name > Interpolate controller name

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))
}
};
}])

AngularJs call controller function from dynamically created element

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: '&'
}
...........
}}]);

Get parameters from routeProvider in element directive

I have an element directive and I want to know if I can get parameters from routeProvider to render my template and set it up in my controller.
adminDash.directive('hospitals', function() {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
};
});
How can I get any parameters in my element directive?
You can isolate the scope of the directive, like this:
adminDash.directive('hospitals', function() {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
scope: {
paramValue: '&',
paramVariable: '=',
},
};
});
check this to understand better https://thinkster.io/egghead/isolate-scope-am/
There are 2 ways to do it: both involve using $routeParams service that allows you to retrieve current set of route parameters.
Given that you have an url: http://example.com/#/hospitals/foobar and a route /hospitals/:hospital/ configured in your $routeProvider, you can:
1.Inject $routeParams into your directive:
adminDash.directive('hospitals', function($routeParams) {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
link: function(scope, element){
scope.hospital = $routeParams.hospital;
}
};
});
2.Inject $routeParams into AdminHospitalsController
adminDash.controller('AdminHospitalsController', function($scope, $routeParams) {
$scope.hospital = $routeParams.hospital;
}
Both method will result in having hospital=foobar in your directive's scope;

Categories

Resources