Angular : issue in my directive to get the original html content - angularjs

I try too create a directive with angular. My goal is too get the original content from my html file in the compile or link function of my directive. Then update this content and for finish change the original content by the updated content in my template of my directive.
For exemple this is my index.html:
<my-directive> Hey this is my original content that I try to get! </my-directive>
This is my directive :
.directive('myDirective', function() {
return {
restrict: 'AE',
transclude: false,
template: '{{UpdatedContent}}',
compile: function(tElement, tAttr) {
console.log(tElement[0]);
},
...
The probleme is that in my compile function or link I can't get my original content each time I tried to look the tElement object I get the "{{UpdatedContent}}".
UPDATE : ANSWER
In fact the solution is to use the function transcludeFn of the compile function.
Here an exemple who works :
compile: function(elem, attrs, transcludeFn) {
var markdownContent = {};
transcludeFn(elem, function(clone) {
/* clone is element containing html that will be transcludded*/
console.log (clone.text());
});
My "clone.text()" is my original html.
I hope this will help some of you!!

You should set transclude : true, you should not do this: template: '{{UpdatedContent}}'.
If you want to get html of element on which your directive were placed in the link function just call:
tElement.html()
Btw. you always get {{UpdatedContent}} because you literally set it to be your template.
UPDATE Working PLNKR.

Related

Adding directives to an element using another directive

I am trying to create a directive that adds some html code but also adds additional attributes/directives.
Using the code below, an ng-class attribute is indeed added, but it seems angular does not recognize it as a directive anymore. It is there, but it has no effect.
How can I get it to work? Thanks.
The Angular code:
angular.module('myModule', [])
.directive('menuItem', function () {
return {
restrict: 'A',
template: '<div ng-if="!menuItem.isSimple" some-other-stuff>{{menuItem.name}}</div>'
+'<a ng-if="menuItem.isSimple" ng-href="{{menuItem.link}}">{{menuItem.name}}</a>',
scope: {
menuItem: '='
},
compile: function (element, attrs) {
element.attr('ng-class', '{active : menuItem.isActivated()}');
}
}
});
And the html:
<li menu-item="menuItem" ng-repeat="menuItem in getMenuItems()" />
EDIT:
The solution by #Abdul23 solves the problem, but another problem arises: when the template contains other directives (like ng-if) these are not executed. It seems the problem just moved.
Is it possible to also make the directives inside the template work?
Or perhaps insert the html using the compile function instead of the template parameter. Since I want a simple distinction based on some value menuItem.isSimple (and this value will not change), perhaps I can insert only the html specific to that case without using ng-if, but how?
You need to use $compile service to achieve this. See this answer.
For your case it should go like this.
angular.module('myModule', [])
.directive('menuItem', function ($compile) {
return {
restrict: 'A',
template: '<a ng-href="{{menuItem.link}}">{{menuItem.name}}</a>',
scope: {
menuItem: '='
},
compile: function (element, attrs) {
element.removeAttr('menu-item');
element.attr('ng-class', '{active : menuItem.isActivated()}');
var fn = $compile(element);
return function(scope){
fn(scope);
};
}
}
});

Angularjs: access template in directive

What I want to do is to append compiled template to some other DOM element in Angualrjs directive. Is it possible? How?
I know you can use transclude to include the template and keep content in the tag, but how do I attach my compiled template to other DOM element?
angular.module("my.directive")
.directive('passwordStrength', [function(){
return {
templateUrl: '/tpl/directive/passwordStrength.html',
restrict: 'A',
link: function postLink(scope, iElement, iAttrs){
console.log('password strength is running');
iElement.append($template) // problem here!!!
}
};
}]);
I'm not sure what you're trying to accomplish overall. You may want to use ng-include to pull in markup from a url, rather than using the templateUrl property, or you may want to use the templateUrl property on one directive, then make another directive and include that directive in the second directive. I made some sample directives to help give you ideas.
.directive('myDirective', function($compile) {
return {
scope: {
path: '=myDirective'
},
link: function(scope, element) {
// rather than use `templateUrl`, I'll get markup from the path using `ng-include`
var html = '<div ng-include="path"></div>';
// manipulate the markup however you want to
html+= '<p>More stuff from "myDirective"!</p>';
// append the markup
element.append(html);
// compile the markup so that Angular will know about it (or use the directive `compile` rather than `link`)
$compile(element.contents())(scope);
}
};
})
// this is sort of like "extending" the other directive.
.directive('myOtherDirective', function() {
return {
scope: {
path: '=myOtherDirective'
},
template: '<p>Stuff from "myOtherDirective"></div><div my-directive="path"></div>'
};
})
Here's a demo you can mess around with.

why ng-transclude not working in angular js as expected

I make a simple directed with isolated scope .I read the tutorial of transclude but when I apply it not working as expected .I need to show "dd" and test together how I can show this
here is my plunker
http://plnkr.co/edit/OxmVga7DdkNxzPnfDtGS?p=preview
var app =angular.module('app',[]);
app.directive('newdir',function(){
return {
restrict:"E",
scope:{
fr:'#'
},
replace:true,
transclude: true, // we want to insert custom content inside the directive
template:"<div ng-transclude >{{fr}}</div>"
}
});
The transcluded element gets completely replaced. Replace your template with this to see what is happening:
<div><h3>BEFORE</h3><h1 ng-transclude>MISSING</h1><h3>AFTER</h3>{{fr}}</div>

AngularJS directive not properly receiving link passed in attribute

I've got an AngularJS directive that is not placing a string (intended to be a relative path to an image) inside one of the attributes in an HTML element and I'm at a loss as to why.
My item looks like the following:
item : {
name: 'Test Name',
link: 'Assets/logo.png'
}
If I step through the javascript, I'm correctly receiving the link from the webservice, so that's not the problem as my Angular controller properly shows the link in the $scope.
The following is what I have in the template for that controller that I'm having the problem with:
<my-directive name="{{item.name}}" link="{{item.link}}"></my-directive>
Here's the javascript for my directive:
angular.module('myModule').directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
templateUrl: '/RelativePathToTemplateFile.html',
scope: {},
link: function($scope, element, attr, model) {
$scope.name = attr.name;
$scope.link = attr.link;
}
}
})
When I look at the rendered HTML, I have the following:
<div name="Test Name" link></div>
What's going on? How can I pass this link in properly?
Directive scope binding technique can resolve this issue. Try to use "#" to bind the directive property to the evaluated DOM attribute.
HTML
<div ng-controller="myCtrl">
<my-directive my-name="{{item.name}}" my-link="{{item.link}}"></my-directive>
</div>
Javascript
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.item = {
name:"Test Name",
link:"Assets/logo.png"
};
})
.directive("myDirective",function(){
return {
restrict: "E",
template: '<div name="{{myName}}" link="{{myLink}}">{{myName}}</div>',
replace: true,
scope:{
myName:"#",
myLink:"#"
}
};
});
Here is a jsFiddle DEMO, you could refer to it.
From the documentation:
function link(scope, element, attrs) { ... } where:
* scope is an Angular scope object.
* element is the jqLite-wrapped element that this directive matches.
* attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values.
so it's "attrs", not "attr"
try:
<myDirective name="item.name" link="item.link"></myDirective>
It will be better :)

angularJS directive with isolated scope, attribute binding doesn't work

Please see this jsfiddle: http://jsfiddle.net/viro/DK5pC/3/
What I did looks right compared to the tutorials and replies I've found, so I'm sure I'm overlooking something trivial.
I'm trying to do a directive on a html element, that will create a sibling div to display a message associated with the original element.
for example, for this html :
<input ng-model="inp" tst-msg="message" />
I would create as a sibling element:
<div class="msg">Msg:<span ng-bind="tstMsg"></span></div>
I was hoping that tstMsg in the div's scope would be bound to message in the input's scope.
Here's what the directive looks like :
angular.module('tst', [])
.directive('tstMsg', function(){
var template = "<div class='msg' >Msg:<span ng-bind='tstMsg'></span></div>";
var link = function(scope,element,attrs) {
element.parent().append(template);
console.log("link called");
};
return {
restrict: 'A',
scope: {
tstMsg: '='
},
link: link
};
});
Well that doesn't work and I can't figure out why.
You need to $compile the template you're adding to the DOM. Angular hasn't had a chance to add it's handlers, for instance the ng-bind directive to that part of the dom.
So instead of just adding the element like this:
element.parent().append(template);
These steps will let Angular process your template and then add it.
newe = angular.element(template);
$compile(newe)(scope);
element.parent().append(newe);
Updated fiddle

Resources