What I want to do is to create an element directive, that can have bindable attributes and can work with static values.
Ex. I have a directive myTag which should support enablel/disable of some features... I want this to work like
<my-tag enable_f1="true" enable_f2="true" />
or like
<my-tag enable_f1="{{mc.someVal1}}" enable_f2="{{mc.someVal2}}" />
Now how can I write link method, to support binding to the attributes as well as static values?
angular.module('TestModule',[])
.directive('myTag',function() {
return {
restrict: 'E',
templateUrl: '<div></div>',
link: function (scope, element, attrs){
//I can get attrs.enable_f1, attrs.enable_f2, but what if it is bound to model?
}
}
});
You can have an isolated scope that gets these values:
HTML:
<my-tag enable-f1="mc.someVal1" enable-f2="mc.someVal2"></my-tag>
<my-tag enable-f1="true" enable-f2="false"></my-tag>
Directive:
myApp.directive('myTag',function() {
return {
restrict: 'E',
template: '<div></div>',
scope: {
enableF1: '=',
enableF2: '='
},
link: function (scope, element, attrs){
console.log(scope.enableF1);
console.log(scope.enableF2);
}
}
});
Fiddle
Related
I have two hierarchical grid (using same directive) with same data in same controller. But when I expand one grid, it also expand the other one. I am using isolate scope.
module.directive('treeGrid', ['$timeout', function($timeout) {
return {
restrict: 'E',
templateUrl:'tree-grid-template.html',
replace: true,
scope: {
treeData: '=',
},
link: function(scope, element, attrs) {
//logic
}
}
}]);
and html is :
<tree-grid tree-data="tree_data"></tree-data>
I have a angular directive:
app.directive('myDirective', function()
{
return{
restrict: 'AE',
scope: {
myCustomer: "&"
},
require: 'ngModel',
link: function(scope, element, attr, ngModel){
var oldVal;
function fromUser(value){
scope.myCustomer()(value, oldVal);
oldVal = value;
return value;
}
function toUser(value){
return value;
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);
}
}
}
At the moment I invoke this director by using attribute name and bind it to a function:
<input type="text" my-directive="showInput" ng-model="user.name">
It works fine but what I want is to use element name, something like this:
<my-directive>
The problem is I don't know how to bind to a function as I do with the attributes.
You will need to set 'restrict' to 'E' in your directive definition something like:
bindToController: true,
controller: 'YourController',
controllerAs: 'vm',
restrict: 'E', //<----this is what you want
templateUrl: 'template.html'
You have to pass restrict: 'E' in directive options
angular.module("image-management")
.directive('myDirective', ($modal) => {
return {
restrict: 'E',
scope:{
showInput: '&'
},
template: '',
link: function(){}
})
<my-directive showInput="showInput" ></my-directive>
<my-directive some-function="someFunction"></my-directive>
Then in your directive link function, it is accesible through attr
link: function(scope, element, attr, ngModel){
// Your logic...
attr.someFunction();
}
As #sumair answered, you can do:
<my-directive showInput="showInput" ></my-directive>
But, if you really want to use only
<my-directive>
AND your directive does not require to have an isolated scope, you can just leave the scope property of the directive definition and reference your showInput function directly from inherited scope like so:
app.directive('myDirective', function()
{
return{
restrict: 'AE',
/*scope: { ////// remove this part //////
myCustomer: "&"
},*/
require: 'ngModel',
link: function(scope, element, attr, ngModel){
var oldVal;
function fromUser(value){
scope.showInput()(value, oldVal);
oldVal = value;
return value;
}
function toUser(value){
return value;
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);
}
}
}
I have a custom directive:
<custom-directive style='height: {{window.innerHeight + "px"}}'></custom-directive>
myApp.directive('customDirective', function(){
return {
restrict: 'E',
templateUrl: '/views/controls/customTemplate.html'
};
});
So, the expression style='height: {{window.innerWidth + "px"}}' doesn't work. App just ignores it. How to make it work?
Write a link function in directive where you will get directive element as and argument use that to change the css of the element.
Like if you want to change the color of the directive text do like this -
link: function(scope, elem, attr) {
elem.css('color','red');
}
Diective
myApp.directive('customDirective', function(){
return {
restrict: 'E',
templateUrl: '/views/controls/customTemplate.html',
link: function(scope, elem, attr) {
elem.css('color','red');
}
};
});
I want to pass a template to a directive like this:
<my-directive template="/templates/my-directive-template.html"></my-directive>
If no template is provided then the standard template is used.
How can I achieve this?
Or shouldn't I do this? I just want to reuse a directive, but want to give it different appearances each time.
Here's the directive... but I'm stuck on how to move forward.
app.directive('my-directive', function(){
return {
restrict: 'E',
scope: {
template: '=template'
},
template: 'standard-template.html'
}
})
templateUrl can be a function, that gets the element and its attributes as arguments. So you can do the following:
app.directive('my-directive', function(){
return {
restrict: 'E',
templateUrl: function(element, attrs) {
return attrs.template || 'standard-template.html';
}
You could use ng-include. So as an example
app.directive('my-directive', function(){
return {
restrict: 'E',
scope: {
template: '=?'
},
template: '<div ng-include="directiveTemplate"></div>',
link: function (scope) {
scope.directiveTemplate = scope.template || '/path/to/default.tpl.html';
}
}
})
How do I get the input element from within the directive before the template overwrites the contents?
html
<div xxx>
<input a="1" />
</div>
js
app.directive('xxx', function(){
return {
restrict: 'A',
template: '<p></p>',
replace: true, //if false, just leaves the parent div, still no input
compile: function(element, attrs) {
console.log(element);
return function (scope, iElement, iAttrs) {
}
}
};
});
i am on angular 1.0.x, I cannot pass in optional scope parameters with the '=?' syntax and i want to be able to override a portion of the default template of the directive in a very flexible way. instead of adding a scope variable or attribute everytime that I just plan on passing through the directive, I want to be able to supply the whole element to be used.
edit
the input must retain the scope of the directive, and not the parent.
edit
I am trying to include a partial template inside a directive that will overwrite a piece of the actual template. The piece I am including therefore needs to have access to the directive's scope and not the parent's.
Update
It seems if I do not provide a template or a template URL and instead replace the contents manually using the $templateCache I can have access to the inner elements. I want to let angular handle the template and the replacement though and just want to be able to access the contents in the directive naturally before they get replaced.
Solution
Plunkr
html
<body ng-controller="MainCtrl">
<div editable="obj.email">
<input validate-email="error message" ng-model="obj.email" name="contactEmail" type="text" />
</div>
</body>
js
app.controller('MainCtrl', function($scope) {
$scope.obj = {
email: 'xxx'
};
});
app.directive('editable', function($log){
return {
restrict: 'A',
transclude: true,
template: '<div ng-show="localScopeVar">{{value}}<div ng-transclude></div></div>',
scope: {
value: '=editable'
},
link: function(scope) {
scope.localScopeVar = true;
}
};
});
app.directive('validateEmail', function($log){
return {
restrict: 'A',
require: 'ngModel',
scope: true,
link: function(scope, el, attrs, ctrl) {
console.log(attrs['validateEmail']);
}
};
});
I believe you're looking for the transclude function (link is to 1.0.8 docs). You can see what's going on with:
app.directive('xxx', function($log){
return {
restrict: 'A',
transclude: true,
compile: function(element, attrs, transclude) {
$log.info("every instance element:", element);
return function (scope, iElement, iAttrs) {
$log.info("this instance element:", element);
transclude(scope, function(clone){
$log.info("clone:", clone);
});
}
}
};
});