How to get evaluated attributes inside a custom directive
Notice: I do update this answer as I find better solutions. I also keep the old answers for future reference as long as they remain related. Latest and best answer comes first.
Better answer:
Directives in angularjs are very powerful, but it takes time to comprehend which processes lie behind them.
While creating directives, angularjs allows you to create an isolated scope with some bindings to the parent scope. These bindings are specified by the attribute you attach the element in DOM and how you define scope property in the directive definition object.
There are 3 types of binding options which you can define in scope and you write those as prefixes related attribute.
angular.module("myApp", []).directive("myDirective", function () {
return {
restrict: "A",
scope: {
text: "@myText",
twoWayBind: "=myTwoWayBind",
oneWayBind: "&myOneWayBind"
}
};
}).controller("myController", function ($scope) {
$scope.foo = {name: "Umur"};
$scope.bar = "qwe";
});
HTML
<div ng-controller="myController">
<div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar">
</div>
</div>
In that case, in the scope of directive (whether it's in linking function or controller), we can access these properties like this:
/* Directive scope */
in: $scope.text
out: "hello qwe"
// this would automatically update the changes of value in digest
// this is always string as dom attributes values are always strings
in: $scope.twoWayBind
out: {name:"Umur"}
// this would automatically update the changes of value in digest
// changes in this will be reflected in parent scope
// in directive's scope
in: $scope.twoWayBind.name = "John"
//in parent scope
in: $scope.foo.name
out: "John"
in: $scope.oneWayBind() // notice the function call, this binding is read only
out: "qwe"
// any changes here will not reflect in parent, as this only a getter .
"Still OK" Answer:
Since this answer got accepted, but has some issues, I'm going to update it to a better one. Apparently, $parse
is a service which does not lie in properties of the current scope, which means it only takes angular expressions and cannot reach scope.{{
,}}
expressions are compiled while angularjs initiating which means when we try to access them in our directives postlink
method, they are already compiled. ({{1+1}}
is 2
in directive already).
This is how you would want to use:
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective', function ($parse) {
return function (scope, element, attr) {
element.val("value=" + $parse(attr.myDirective)(scope));
};
});
function MyCtrl($scope) {
$scope.aaa = 3432;
}
.
<div ng-controller="MyCtrl">
<input my-directive="123">
<input my-directive="1+1">
<input my-directive="'1+1'">
<input my-directive="aaa">
</div>
One thing you should notice here is that, if you want set the value string, you should wrap it in quotes. (See 3rd input)
Here is the fiddle to play with: http://jsfiddle.net/neuTA/6/
Old Answer:
I'm not removing this for folks who can be misled like me, note that using $eval
is perfectly fine the correct way to do it, but $parse
has a different behavior, you probably won't need this to use in most of the cases.
The way to do it is, once again, using scope.$eval
. Not only it compiles the angular expression, it has also access to the current scope's properties.
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
element.val("value = "+ scope.$eval(attr.value));
}
});
function MyCtrl($scope) {
}
What you are missing was $eval
.
http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval
Executes the expression on the current scope returning the result. Any exceptions in the expression are propagated (uncaught). This is useful when evaluating angular expressions.
AngularJs directives - how to get attributes values from within directive
Use $observe
:
Observing interpolated attributes: Use
$observe
to observe the value changes of attributes that contain interpolation (e.g.src="{{bar}}"
). Not only is this very efficient but it's also the only way to easily get the actual value because during the linking phase the interpolation hasn't been evaluated yet and so the value is at this time set toundefined
. -- directives doc
return function(scope, element, attrs) {
attrs.$observe('key', function(value) {
console.log('key=', value);
});
}
As @FMM mentioned in a comment, data
is stripped by Angular when it normalizes the attribute name, hence the use of key
above, rather than dataKey
.
How to access elements attributes from custom directive while keeping access to parent scope?
For what you are trying to do, do not need a two way binding. You are trying to access the text assigned as attribute. You could just write your directive as:-
.directive('testDirective', function(){
return {
restrict:"E",
//scope:true, //apply if required
templateUrl:"directive.html",
link:function(scope, elm, attrs){
scope.testAttribute = attrs.testAttribute; //Get it from attributes
}
};
});
Demo
Now here scope property of directive settings is going to use the parent scope itself. But ideal scenarios you may want to use scope:true
(Child scope of parent) or a 2 way binding
wit isolated scope. But at this point, since not really sure what is your original goal, this is a solution based on what you have in your question.
So to summarize:-
I want to be able to access the parent scope of the directive I have created
Remove the isolated scope and just use parent's scope.
but I also want to be able to access the attributes that I have placed onto the element.
Use attrs
argument of the link function (attrs.testAttribute
). If you want to evaluate it as a bound value the do (scope.$eval(attrs.testAttribute)
)
How to evaluate attributes inside an angular directive
Just use a single template:
<span>{{lang}}</span>
<img ng-if="lang !== '--' && lang !== '??'" ng-src="img/{{lang}}.png" />
AngularJS custom attribute does not evaluate first time directive runs
As it turns out the controller and controllerAs properties were having an effect on this. I removed it, but then decided I would rather have the controller so instead I used isolate scope to evaluate the object instead of reading it from the attr property.
AngularJS: How to set an attribute to a custom directive
Go Angular :-)
You don't need the use of jQuery here. Angular is sufficient enough. You can change your code like this:
In your View:
<keybuddy model="myInputText"></keybuddy>
<button ng-click="showText()">Show Text</button>
In your View controller:
$scope.showText = function() {
console.log($scope.myInputText);
}
And update your directive to have scope
like below (replace your `scope: true):
scope: {
inputText: '=model'
}
Read more on Isolating scope of a directive
angular directive attributes not evaluated
1) Complex attributes are not being passed as objects despite using '=' (see code below) in scope
That is because you are getting them as attrs.whenNormal
which is a string (JSON). You instead just need to access it from scope, i.e scope.whenNormal
. It would just be same as scope.$eval(attrs.whenNormal)
or JSON.parse(attrs.whenNormal)//provided your JSON is valid
.
But the 2 way binding here doesn't make much sense though.
2) the function that should evaluate to provide one-way binding is also being passed as string instead.
That is because when you use function binding they get evaluated as getter with bound values (you specified bound value as RestEditCtrl.restaurant.id
). Inorder to access the value, provided the function ajaxState
returns something, you need to do curState = scope.btnState();
instead of curState = attrs.btnState
, basically evaluate the getter to get the value.
Plnkr
Related Topics
Angularjs Changes Urls to "Unsafe:" in Extension Page
How to Map More Than One Property from an Array of Objects
Remove Not Alphanumeric Characters from String
Remove All Event Listeners of Specific Type
Best Way to Call an Asynchronous Function Within Map
Smooth Scroll to Div Id Jquery
How to Synchronously Determine a JavaScript Promise's State
Getting Scroll Bar Width Using JavaScript
Cloud Firestore Case Insensitive Sorting Using Query
Test If Event Handler Is Bound to an Element in Jquery
Returning Chrome Storage API Value Without Function
Multiple Left-Hand Assignment with JavaScript
How to Destructure Object Properties with Key Names That Are Invalid Variable Names