I had a directive,
.directive('lbd', function () {
return {
restrict: 'E',
scope: {
context: '=',
dui: '='
},
templateUrl: 'app/templates/lbd-directive.html',
});
Sometimes I call this without any atttrs but I am not sure how to do that.
This is not working,
<lbd class="col-xs-12 lbd" context="" dui="" ></lbd>
Can anyone please help me.Thanks.
Try in this way
.directive('lbd', function () {
return {
restrict: 'E',
scope: {
context: '=?', // notice the ? makes this parameter optional.
dui: '=?' // notice the ? makes this parameter optional.
},
templateUrl: 'app/templates/lbd-directive.html',
});
Your directive is correct. It's only missing unclosed bracket which should throw an error in the log. code should be
.directive('lbd', function () {
return {
restrict: 'E',
scope: {
context: '=',
dui: '='
},
templateUrl: 'app/templates/lbd-directive.html'
}
});
you could see the running code here
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 ...
}
};
}
.directive('clinicalTrailModal', function ($compile) {
return {
restrict: 'EA',
scope: {
context: '=',
dui: '='
},
templateUrl: 'app/templates/lbdAdsModal.html'
})
I am calling this directive based on true false condition like below,
<clinical-trail-modal value="currentUrl" dui="typeDisease._id" data-ng-if="clinicalTrailModal"></clinical-trail-modal>
But it does'nt work.When I remove
restrict: 'EA',
scope: {
context: '=',
dui: '='
},
this it works.I am new to angularjs.Can anyone please help me.Thanks.
It's possibly failing due to you passing context into the scope. Either remove context, pass it in, or make it optional.
restrict: 'EA',
scope: {
context: '=?', //optional
dui: '='
}
I want to get a value straight from an attribute directive:
<form cronos-dataset="People as p">
Form Content
</form>
In my JS I tried:
app.directive('cronosDataset',[function() {
return {
restrict: 'A',
controller: 'CronosGenericDatasetController',
scope: {
"cronos-dataset" : '#'
}
};
}])
.controller("CronosGenericDatasetController",['$scope', function($scope) {
alert($scope["cronos-dataset"]);
}]);
I want to alert "People as p" string but I get undefined. Is that right path or should I go thorough a different approach?
You are supposed to have camelCase in the scope declaration
app.directive('cronosDataset',[function() {
return {
restrict: 'A',
controller: 'CronosGenericDatasetController',
scope: {
cronosDataset : '#'
}
};
}])
Here is a demo to see different variations
http://plnkr.co/edit/G6BiGgs4pzNqLW2sSMt7?p=preview
Make a link function instead:
app.directive('cronosDataset',[function() {
return {
scope: {},
restrict: 'A',
link: function (scope, elem, attrs) {
alert(attrs.cronosDataset);
}
I have the following directive:
app.directive('skiTest', function($timeout,$compile) {
return {
'replace': true,
'restrict': 'E',
'scope': {
'data': '=',
'selecto': '#',
'ngModel': '='
},
link: function (scope, element, attrs) {
attrs.$observe("selecto", function () {
$timeout(function () { // we need a timeout to compile after the dust has settled
$compile(element.contents())(scope); //recompile the HTML, make the updated content work.
},0);
});
},
'template':'<div><select name="testSelect" ng-model="ngModel" ng-options="{{selecto}} in data"><option value="">Code</option></select></div>'
}
});
http://jsfiddle.net/L269zgbd/1/
If i'll try to select a country in the directive selection box, the ng-model object is being set to null.
Any idea why is that and how can i solve this problem?
Basically i want the same behavior on the directive selection as the one i get with the non directive selection.
Thanks!
If you upgrade the version of angular used in the fiddle the following works without using $compile or $timeout
app.directive('skiTest', function () {
return {
'replace': true,
'restrict': 'E',
'scope': {
'data': '=',
'selecto': '#',
'ngModel': '='
},
'template': '<div><select name="testSelect" ng-model="ngModel" ng-options="{{selecto}} in data"><option value="">Code</option></select></div>'
}
});
DEMO
If you can't upgrade your version of angular like charlietfl suggests you can use the $compile function instead:
app.directive('skiTest', function($timeout,$compile) {
return {
'replace': true,
'restrict': 'E',
'scope': {
'data': '=',
'selecto': '#',
'ngModel': '='
},
'template':'<div><select name="testSelect" ng-model="ngModel" ng-options="{{selecto}} in data" ng-change="changed()"><option value="">Code</option></select></div>',
compile: function(tElement, tAttributes){
tElement[0].innerHTML = tElement[0].innerHTML.replace('{{selecto}}', tAttributes.selecto);
}
}});
jsfiddle: http://jsfiddle.net/r366r3b7/
I understand that I can dynamically set a templateUrl base on an option DOM attribute template-url="foo.html" given the following code:
angular.module('foo').directive('parent', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// code
},
templateUrl: function(elem,attrs) {
return attrs.templateUrl || 'some/path/default.html'
}
}
});
However, I need to take this a step further and pass this string one level deeper, to a child directive.
Given this HTML:
Usage in Main project
<parent parent-template="bar.html" child-template="foo.html"></parent>
The child will not be exposed in most cases, so if child-template is set, it needs to implicitly replace templateUrl for all child <child></child> elements that are located in the parent foo.html.
The require: '^parent' attribute passes data from scope to scope, but I'm not seeing this available in templateUrl when it's declared.
foo.html
<h1>Title</h1>
<child ng-repeat="item in array"></child>
Directives
angular.module('foo').directive('parent', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// code
},
templateUrl: function(elem,attrs) {
return attrs.parentTemplate || 'some/path/default.html'
},
scope: {
childTemplate: '=childTemplate'
}
}
})
.directive('child', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// code
},
templateUrl: function(elem,attrs) {
return ??? // parent.attribute.childTemplate? || 'some/path/default.html'
},
require: '^parent',
scope: {
childTemplate: '=childTemplate'
}
}
});
Update
The old answer (see bellow) won't work because it's only possible to access the controller of the required directives inside the link functions, and the templateUrl function gets executed before the link functions.
Therefore the only way to solve this is to handle everything in the templateUrl function of the child directive. However this function only takes 2 arguments: tElement and tArgs.
So, we will have to find the element of the parent directive and access the attribute child-template. Like this:
angular.module('testApp', [])
.directive('parent', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
},
transclude:true,
templateUrl: function(elem,attrs) {
return attrs.parentTemplate || 'default.html'
}
}
})
.directive('child', function() {
return {
restrict: 'E',
require:'^parent',
templateUrl: function(elem,attrs) {
//if jQuery is loaded the elem will be a jQuery element, so we can use the function "closest"
if(elem.closest)
return elem.closest("parent").attr("child-template") || 'default.html';
//if jQuery isn't loaded we will have to do it manually
var parentDirectiveElem=elem;
do{
parentDirectiveElem=parentDirectiveElem.parent();
}while(parentDirectiveElem.length>0 && parentDirectiveElem[0].tagName.toUpperCase()!="PARENT");
return parentDirectiveElem.attr("child-template") || 'default.html';
}
}
});
Example
Old Answer
Since you are isolating the scope, you could try this, it's a bit hacky but I guess that it should work:
angular.module('foo').directive('parent', function() {
return {
restrict: 'E',
controller: function($scope) {
this.childTemplate=$scope.childTemplate;
},
link: function(scope, element, attrs) {
},
templateUrl: function(elem,attrs) {
return attrs.parentTemplate || 'some/path/default.html'
},
scope: {
childTemplate: '#'
}
}
})
.directive('child', function() {
return {
restrict: 'E',
require: '^parent',
link: function(scope, element, attrs, parentController) {
if(parentController.childTemplate)
element.data("childTemplate", parentController.childTemplate);
},
templateUrl: function(elem,attrs) {
return elem.data("childTemplate") || 'some/path/default.html'
}
}
});
In my question, I was attempting to provide an override for the templateUrl of an off-the-shelf directive that didn't have one. My original question doesn't mention this, however, I wanted to add this as a reference to others who may have forgotten, as I did. Angular allows you to decorate directives and override their properties.
app.config(function($provide) {
$provide.decorator('child', function($delegate) {
var directive = $delegate[0];
directive.templateUrl = 'path/to/custom.html';
return $delegate;
});
});