How to make expressions computable in custom directive? (angularjs) - angularjs

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

Related

How to invoke a directive by using element name?

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

Angular.JS binding attribute in element directive

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

Attribute without value in AngularJS directive

I've written a directive with an isolate scope.
app.directive('myDirective', function() {
return {
restrict: 'E',
scope {
attr1: '#',
attr2: '#',
noValueAttr: // what to put here?
},
link: function(scope, elem, attrs) {
// how to check here if noValueAttr is present in mark-up?
}
};
});
the html could be
<my-directive attr1='...' attr='...' ... no-value-attr>
or
<my-directive attr1='...' attr='...' >
I am wondering how to use (and have the directive detect if it's there or not) an optional attribute which has no assigned value. Thanks.
Just use attrs.hasOwnProperty('noValueAttr') in the link function to test whether the attribute is present or not.
Don't forget the attribute in markup would be no-value-attr, not noValueAttr like you showed.
link: function(scope, elem, attrs) {
if (attrs.hasOwnProperty('noValueAttr'))
// attribute is present
else
// attribute is not present
}
I know it is an old question, but there is that way to:
link: function(scope, elem, attrs) {
scope.noValueAttr = scope.$eval(attrs.noValueAttr) || 'default value';
}

Require one attribute between choices in directive

I am creating an angular directive and I want the user to specify a 'type' of the directive.
For example:
<my-directive type-a></my-directive>
or
<my-directive type-b></my-directive>
or
<my-directive type-c></my-directive>
I know I can do:
<my-directive type="a"></my-directive>
and then require the type attribute but then I'm doing string matching. Is there anyway to do this by requiring one of 'type-a', 'type-b', or 'type-c' to be present?
Without much background info, I came up with this solution.
JSFIDDLE
So basically myDirective has a controller which is shared by type directives (type-a, type-b.. and so on). The type directive sets the type on the scope of myDirective.
myApp.directive('myDirective', function() {
return {
restrict: 'E',
controller: function($scope) {
$scope.type = '';
this.setType = function(type){
if($scope.type === '') $scope.type = type;
else throw 'type can be only defined once. Current type is '+$scope.type
}
},
link: function(scope, elem, attrs) {
console.log(scope.type);
}
}
});
myApp.directive('typeA', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeA');
}
}
});
myApp.directive('typeB', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeB');
}
}
});
I think you can do <div data-my-directive="a"></div> which is a lot safer for cross-browser and w3c. Then the directive would be something like:
.directive('myDirective', function() {
return {
restrict: 'A',
scope: {
type: '='
},
link: function(scope,element,attrs){
}
};
});

Prevent angular from copying attributes when replace=true

The following directive:
var app = angular.module('demo', []);
app.directive('myDirective', function() {
return {
restrict: 'E',
template: '<h1>Foo bar</h1>'
};
});
With the following usage:
<my:directive foo="bar"></my:directive>
Renders the following HTML:
<my:directive foo="bar"><h1>Foo bar</h1></my:directive>
Since I want to replace my directive with the provided template I set replace:true. This produces the following HTML:
<h1 foo="bar">Foo bar</h1>
Note that Angular copies my directive's attributes to the template elements (the foo="bar"). How can I prevent this behaviour?
You can manually remove the attributes in the link function of the directive:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
template: '<h1>Foo bar</h1>',
link: function(scope, elm, attrs){
elm.removeAttr('foo');
}
};
});
Here's a fiddle with this directive working in your situation.
EDIT: You can extend this to remove all attributes dynamically with a simple loop:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
template: '<h1>Foo bar</h1>',
link: function(scope, elm, attrs){
for(var attr in attrs.$attr){
elm.removeAttr(attr);
}
}
};
});

Resources