So I am so confused! I have HTML that looks like this:
<span paper-embed="" url="theUrl"></span>
and theUrl is a variable that loads a different URL from my ng-controller. Then I have an Angular directive looks like this:
app.directive('paperEmbed', function() {
return {
restrict: 'AEC',
transclude:true,
scope: {
key: '=',
value: '='
},
link: function(scope, element, attrs) {
// is does some jQuery here
}
};
});
my question is, I want to access the URL inside the directive - the variable named theUrl, so how do I do that? I looked up on SA and seemed like
console.log({{theUrl}});
might work but it does not.
Change your scope to
scope: {
key: '=',
value: '=',
url: '='
},
And in your link function you can use it like scop.url
You can access it with attrs.url
Since you are trying to implement a directive with the following:
<span paper-embed="" url="theUrl"></span>
you should use restrict: 'A',
the url attribute can be accessed either through your scope declaration as # or through the attrs object passed into your link function.
as to the console.log({{theUrl}}). {{}} is specifically design to interpolate javascript-keys in the markup, that is processed through the $compile cycle.
Here is something to get you started:
HTML
<span paper-embed url="http://example.com" />
javascript
var app = angular.module('exampleApp', []);
app.directive('paperEmbed', function() {
return function(scope, elem, attrs) {
console.log(attrs.url);
};
});
get a little more detailed information here: https://docs.angularjs.org/api/ng/service/$compile#directive-definition-object
You can either use attrs.url to access it or you can add the url to the scope:
app.directive('paperEmbed', function() {
return {
restrict: 'AEC',
transclude:true,
scope: {
key: '=',
value: '=',
url: '#'
},
link: function(scope, element, attrs) {
console.log(scope.url);
}
};
Whenever you add a variable to the scope like above, the directive is expecting an html attribute to supply that value. In this case url.
<div paper-embed="obj1" key="obj2" value="obj3" url="obj4"></div>
scope.url === obj4;
Among many others, there are two easy ways to do this:
- First method is to access it using the attrs.
- Second method is to pass the parameters by defining in the scope.
First method is to use attrs. attrs has all the attributes. You can simply access the url in the link function as attrs.url
link:function(scope,element,attrs){
console.log(attrs.url)
}
You will see whatever is placed instead of theUrl is displayed on the console.
The other alternative is to change your directive to the following:
app.directive('paperEmbed', function() {
return {
restrict: 'AEC',
transclude:true,
scope: {
key: '=',
value: '=',
theUrl: '='
},
link: function(scope, element, attrs) {
// is does some jQuery here
}};});
Now you can access it in the link function as scope.url. To set the value to be passed simply set $scope.theUrl='whatever your url is' in your ng-controller.
Related
I'm working on creating an angular directive (element) that will apply some transformation to the text within.
Here is the directive:
module.directive('myDir', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
console.log(elem.text());
},
};
});
For now I've just placed a console.log in there to make sure I am seeing the expected text.
If my html is like this it works as expected:
<my-dir>Hello World!</my-dir>
However, if I use a variable from the scope such as this:
<my-dir>{{myMessage}}</my-dir>
Then that is the text I seen in the console output instead of the variables value. I think I understand why the output is this way, however I'm not sure how to get the correct value. The requirement is that the directive should be able to transform text from both examples.
Thoughts?
Use $interpolate service to convert the string to a function, and apply the scope as parameter to get the value (fiddle):
module.directive('myDir', function($interpolate) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
console.log($interpolate(elem.text())(scope));
},
};
});
If you really interested get the interpolated content then do use $interpolate service to evaluated the interpolated content.
Code
link: function(scope, elem, attrs) {
console.log($interpolate(elem.text())(scope));
},
Don't forget to add $interpolate as dependency on directive function.
Have a look on $compile or http://odetocode.com/blogs/scott/archive/2014/05/07/using-compile-in-angular.aspx
This should work:
module.directive('myDir', function($compile) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
console.log($compile(elem.text())(scope));
},
};
});
I would suggest you use an isolated scope on directive which will give you access to the value without having to get it from the dom. You will also be able to manipulate it directly in the link function as part of scope
<my-dir my-message="myMessage"></my-dir>
JS
module.directive('myDir', function() {
return {
restrict: 'E',
template: '{{myMessage}}',
scope:{
myMessage: '=',
},
link: function(scope, elem, attrs) {
console.log(scope.myMessage);
},
};
});
I have one concern when creating a custom directive in angular.
When I'm using a link function, I'm not sure what is the real difference when accessing attributes with attrs or scope.
Take this piece of code for example:
myApp.directive('someDirective', function() {
return {
restrict: 'E',
replace: true,
scope: {
title: '=title'
},
template: '<img/>',
link: function(scope, element, attrs) {
if (scope.title) {
// do something here
}
if (attrs.title){
// do something here
}
},
}
From my observations accessing 'title' attribute from attrs and by scope has a similar effect. What is the real difference?
The difference is that attribute is of a String type by definition. Always. In your case attrs.title will be literally string equal to whatever you pass into attribute in HTML.
However, scope.title is parsed and evaluated result of the attribute attr.title.
Ex. If you use something like this in HTML
<some-directive title="name"></some-directive>
where $scope.name = "Thomas Mann" defined in the scope, then attr.title will be string "name", while scope.title will be "Thomas Mann".
I have a directive that wraps around another directive . The child directive accepts an "options" object as an attribute. I want to create this options object in the parent directive's link function and then set it as an attribute on the child directive in the parent's template, but the options object does not get set if its created dynamically. This works if the options object is set statically in the template itself.
I have a plunker here: http://plnkr.co/edit/gNeKMcneO8RDBmlmpt72?p=preview
Any pointers would be greatly appreciated!!
angular.module('nestedDirectives', [])
.directive('fruitinfo',
[
function() {
return {
restrict: 'A',
scope: {
fruitname: '#?'
},
template: '<br>Fruit Name: {{fruitname}}<br>Fruit Options: {{fruitoptions}}',
link: function(scope, element, attrs) {
scope.fruitoptions = scope.$eval(attrs['fruitinfo']);
}
};
}])
.directive('fruits',
[
function() {
return {
restrict: 'E',
scope: {
selectedFruits: '=?',
btnSizeClass: "#?"
},
template: 'btnSizeClass: {{btnSizeClass}}<br>Fruits: {{fruits}}<br><div ' +
' fruitinfo="fruitOptions" ' +
' fruitname="{{f}}"' +
' ng-repeat="f in fruits">' +
'</div><br><br>' +
'<div fruitname="With static fruitOptions: {{f}}" fruitinfo="{test: \'testOption\', btnSizeClass: \'btn-xs\'}" ng-repeat="f in fruits"></div>',
link: function(scope, element, attrs) {
scope.fruitOptions = {test: 'testOption', btnSizeClass: scope.btnSizeClass};
scope.fruits = ['Apple', 'Banana', 'Watermelon', 'Strawberry'];
}
};
}]
)
;
any particular reason why you are using $eval instead of using "&" in your scope definition like this
http://plnkr.co/edit/W47LZsQ3i4zS8Feu7sDl?p=preview
if you use
fruitoptions:'&fruitinfo'
and then you do
scope.fruitoptions=$scope.fruitoptions()
in your link function you'll get the evaluated expression in its original scope, also consider doing this on the controller function which is invoked prior the link cycle
I figured it out. The "fruitOptions" value must be serialized so that the template can compile it as an attribute, which can then be converted back to an object using "eval" in the nested directive. Plunker updated.
I would like to pass an object to the directive scope:
JS:
app.directive('validatePrice', function() {
return {
link: function(scope, el, attrs){
console.log(attrs.validatePrice);
}
};
});
HTML
<button validate-price="{priceValid: {'disabled': 'disabled'}}">Checkout</button>
where priceValid is a boolean from the controller scope and {'disabled': 'disabled'} is just a plain object. I expect my attrs.validatePrice to return eg:
{
true: {'disabled': 'disabled'}
}
Yet it returns string. How do I do that? :)
I don't think what you want is possible. priceValid will be interpreted as an object key by JavaScript – it will not be interpreted as true.
Anyway, $parse or $eval is what you need to use to pass an object to a directive (if you are not using an isolated scope):
<button validate-price="{priceValid: {'disabled': 'disabled'}}">Checkout</button>
app.directive('validatePrice', function($parse) {
return {
link: function(scope, el, attrs){
var model = $parse(attrs.validatePrice);
console.log(model(scope));
console.log(scope.$eval(attrs.validatePrice));
}
};
});
fiddle
Use $parse if you need to alter the object. See https://stackoverflow.com/a/15725402/215945 for an example of that.
<validate-price-dir validate-price="{priceValid: {'disabled': 'disabled'}}">Checkout</validate-price-dir>
app.directive('validatePriceDir', function() {
return {
restrict: 'E',
scope: { validatePrice: '=validatePrice' },
link: function(scope, el, attrs){
console.log(scope.validatePrice);
}
};
});
I'm having issues getting an object to pass to my directive. I believe I've done things correctly, but after failed attempt after failed attempt I must seek help. What did I miss here that's stopping me from passing an array to my directive?
HTML:
<div class="body">
{{orderList.length}} //shows up as 18
</div>
<queue-summary orders="orderList"></queue-summary>
Javascript:
directive('queueSummary', function () {
return {
scope: {
orders: '='
},
replace: true,
restrict: 'E',
templateUrl: '/partials/admin/bits/queue-summary.htm',
link: function (scope, element, attrs) {
console.log(scope, element, attrs); //$attrs.orders show it as the String "orderList" instead of the array
}
}
}).
It's worth noting that you can access the bound value of an attribute you don't have isolate scope on with $eval:
scope.$eval(attrs.orders)
attrs will just show you the string value of an attribute. In order to access the passed object, use the isolate binding you created:
console.log(scope.orders);