I have a custom directive and rendering that directive using ng-repeat. what I need is I want to compile interpolation before passing into my custom directive.
Find plnkr below
https://plnkr.co/edit/bjdBSKCFPhgbE2aREupy?p=preview
Here I want to compile interpolation in this code <display-id mycompile id={{op.id}}> </display-id> using mycompile directive.
app.directive('mycompile', function ($compile, $interpolate) {
return {
restrict: 'EA',
replace: true,
compile: function ($scope, $elm, $attrs) {
return {
pre: function ($scope, $elm, $attrs) {
$interpolate($elm[0])($scope);
}
}
}
}
})
$interpolateProvider expects string to be an argument, so what you need is to convert your element to string and then back to DOM element if you want,
it could be achieved with outerHTML property like so:
$interpolate($elm.prop('outerHTML'))($scope);
Related
I have this:
angular.module("angular-table").directive("atPagination", [
function() {
return {
restrict: "E",
scope: false,
replace: true,
template: paginationTemplate,
link: function($scope, $element, $attributes) {
//The function name
let fn = '$scope.' + $attributes.getDataFn;
console.log($scope.$eval(fn),$attributes,$attributes.getDataFn, "$eval", fn);
}
}
}
I am calling the function using $scope.$eval in the console(last line). But the function is not getting called.
I am trying to change this library I am using for table and pagination. I am trying to pass a function from my controller into its directive so that it gets called when next is clicked in the pagination.
I can't pass the function the regular way because the scope is false and I don't want to change it. So I am passing it like this
<at-pagination at-config="tableConfig"
get-data-fn="getPaginatedData()" at-list="personnelsdata">
</at-pagination>
I am trying to call the function using $eval but it's not working. What am I doing wrong?
app.directive("myDirective", function() {
return {
restrict: "E",
scope: false,
template: paginationTemplate,
link: function(scope, element, attrs) {
//The function name
̶l̶e̶t̶ ̶f̶n̶ ̶=̶ ̶'̶$̶s̶c̶o̶p̶e̶.̶'̶ ̶+̶ ̶ ̶$̶a̶t̶t̶r̶i̶b̶u̶t̶e̶s̶.̶g̶e̶t̶D̶a̶t̶a̶F̶n̶;̶
let fn = attrs.getDataFn;
console.log(scope.$eval(fn));
}
})
The scope.$eval method evaluates an AngularJS function, not a JavaScript function.
For more information, see
AngularJS Developer Guide - AngularJS Expressions vs. JavaScript Expressions
AngularJS scope API Reference - $eval
I try to loop a function through a nested directive. From the console.info in myCtrl I would expect the string "this should be logged".
angular.module('myApp')
.controller('myCtrl', function ($scope) {
$scope.aFunction = function(input) {
console.info(input.message);
}
})
.directive('levelOneDirective', function () {
return {
templateUrl: '<level-two-directive aFunction="aFunction(object)"></level-two-directive>',
restrict: 'EA',
scope: {
aFunction:"&"
},
link: function (scope, element, attrs) {
}
};
})
.directive('levelTwoDirective', function () {
return {
templateUrl: '<div ng-click="aFunction({message: 'this should be logged'})"></div>',
restrict: 'EA',
scope: {
aFunction:"&"
},
link: function (scope, element, attrs) {
}
};
});
And in my index.html I have something like:
<div ng-controller="myCtrl">
<level-one-directive aFunction="aFunction(object)"></level-one-directive>
</div>
But the console says undefined.
How to connect a function through nested directives?
You have several mistakes in your code but I assume it's because you try to adjust it to the question (such as aFunction as attribute instead of a-function and templateUrl instead of template).
You can have a 2-way binding (=) in your directives (both of them):
scope: {
aFunction:"="
},
And pass the function reference without the object:
<level-one-directive a-function="aFunction"></level-one-directive>
In the second directive HTML have:
<div ng-click="invokeFunction()"></div>
And then in the link function of your 2nd directive you can do:
scope.invokeFunction = function () {
scope.aFunction({message: 'this should be logged'});
}
The above works and I find it more convenient than & binding, which as you can see, is not quite easy to work with, and frankly I haven't messed around enough with it to figure out how (and if possible) to pass arguments through it.
I've seen this question, but it's binding straight on the link function, and you want it with an ng-click so it might not work for you. But perhaps you'll find your solution there.
I have several directives that use the same link function. (The link function adds some extra state and html depending on the use case.) So I declared this as follows:
function common_linkfunc(){...}
var Directive_1 = function($scope, etc) {
return {restrict:"E", ...
link: common_linkfunc,
controller: function($scope, etc) {...}
};
}
Directive_1.$injects = ["$scope", "etc"];
angular.module("module").directive("D1", Directive_1)...;
First change was when link function required $compile. Next I need to add $templateCache and my question is how can I do this systematically?
My first approach was to rewrite common_linkfunc as
function foo($compile, $templateCache) {
return common_linkfunc($compile, $templateCache) {...}
}
and then use this in every directive:
...
link: foo($compile, $templateCache),
...
But this is copy-and-paste! Is there an easier and less error prone way to do the same?
Regardless of the solution, you'll need to pass some argument to your common link function, because Angular won't inject anything into it for you. That being said, I can think of two different approaches:
1) Use arguments
app.directive('foo', function($http, $timeout) {
return {
restrict: 'E',
link: linkFn1.apply(null, arguments)
}
});
function linkFn1($http, $timeout) {
return function(scope, element, attrs) {
// ...
};
}
The downside here is that the order of the arguments in the directive function matters. If some other directive uses a different order, the code won't work properly.
2) Use $injector
app.directive('bar', function($injector) {
return {
restrict: 'E',
link: linkFn2($injector)
}
});
function linkFn2($injector) {
var $http = $injector.get('$http'),
$timeout = $injector.get('$timeout');
return function(scope, element, attrs) {
// ...
};
}
Working Plunker
For some reason Angular isn't catching my data-src
When I do this:
<div foo data-src="{{ my_url }}"></div>
I get back nothing. However, it works when I manually type it: i.e
<div foo data-src="blah"></div>
What am I doing wrong here?
More of my code:
var foo = angular.module('foo', []);
foo.directive('foo', function ($document, $rootScope, $http, $resource) {
return {
restrict: 'A',
scope: true,
link: function (scope, elem, attrs) {
console.log(attrs.src)
}
});
[Edit]
I forgot to use camelCase for the attribute name when calling attrs.$observe(). Also, it looks like you do need to use ng-data-source). Correction made below...
You want to use attrs.$observe() in the link function for your directive. Angular will watch the attribute and execute a callback so the directive can be notified when the value of the interpolated expression changes.
Here's a link to a fiddle created by Mark Rajcok that demonstrates it. And a link to the documentation as well.
Finally, here is some sample code using your directive:
var foo = angular.module('foo', []);
foo.directive('foo', function ($document, $rootScope, $http, $resource) {
return {
restrict: 'A',
scope: true,
link: function (scope, elem, attrs) {
attrs.$observe('ngDataSrc', function(newValue) {
console.log('interpolated value', newValue);
}
}
});
Righty, so I'm just getting into directives and they seem pretty awesome. I ran into a problem though:
I need to pass an array of images into a directive so I can filter them by certain criteria. Here's my html invoking the directive:
<img cover="{{challenge.images}}">
This is my directive:
myproject.directive('cover', function() {
return {
link: function ($scope, element, attrs) {
console.debug("attrs.cover", Array(attrs.cover));
}
};
});
The output is a String. is there a way to prevent attr turning into a String?
I'm assuming here that you don't want to create isolated scope, so:
myproject.directive('cover', function($parse) {
return {
link: function ($scope, element, attrs) {
var covers = $parse(attrs.cover)($scope);
console.debug("attrs.cover", covers);
}
};
});
and then use the directive like so:
<img cover="challenge.images">