AngularJS - How to transclude into a script element? - angularjs

See Plunker
I would like to transclude the content of the directive element into a <script> element.
In the below directive, transclusion does not work when the template contains a script tag as in the following:
app.directive('mdl', function(){
return {
restrict: 'EA'
, replace: true
, transclude: true
, template: '<script id="modal.html" > <div ng-transclude> </div> </script>'
}
})
where the directive is invoked as follows:
<mdlbody> <div>testing modal body</div> </mdlbody>
The resulting <main> element is empty. However, transclude works as expected when the <script> tag is removed from the template string like so,
template: '<div ng-transclude> </div>'
or template: <div> <div ng-transclude> </div> <div>
As long as the template string is not wrapped in <script> , the transclude works.
Transclude also works when ng-transclude is placed directly on <script ng-transclude>. However I want to insert the transclude at a deeper level of nesting inside the <script> element.
Why is this so? How can I get transclude to work with the <script> element in template string? (so that the directive's content is transcluded into the <script> element)
P.S: To clarify further, I am trying to transclude into the script element so the end result should be <script><main> transcluded content</main></script>
(not <main> transcluded content</main>).

if you are trying to refer to a template for this directive then replace template with templateurl because template expects some html code with angular directives write this:
app.directive('mdl', function(){
return {
restrict: 'EA'
, replace: true
, transclude: true
, templateUrl: 'modal'
}
})
and place the below lines at the end of your .htm file
<script type="text/ng-template" id="modal" > <main ng-transclude> </main> </script>

Related

angularjs directive is not recognized

I created an angularjs directive and it is not recognized when executed.
app.directive('someDirective', function(){
return {
restrict: 'AE',
replace: 'true',
transclude: 'true',
scope: {
info: "="
},
templateUrl: '../info.html'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
// info.html
<div>
<img ng-src="someimage.jpg"/>
</div>
<div ng-transclude></div>
//index.html
<ul>
<li ng-repeat="part in parts">
<some-directive info="part">
<div>
click here
</div>
</some-directive>
</li>
</ul>
maybe it is something with the ng-repeat?
I have a directive that looks just like it and it works..
Thank you!
answers for some of the questions:
I didn't add all of my app code.. only the parts relevant to the question.
There are other directives in the code that are written similar to this one,
they are placed in the same file as this one so the path is definitely right.
All templates are placed in the same directory this directive so again - templateUrl is right.. but for some reason this is the only directive that doesn't show. and there is no error in the console.
when putting a breakpoint in the directive return code it does not stop there.. it's like the directive is not recognized at all.

Transclude directive fails to modify content

I have defined a transclude directive as beliw in AngularJs 1.3 - but it does not seem to have any effect on the rendering.
A log statement in the link phase shows that the directive is invoked though.
index.html
<html lang="en" ng-app="directivesApp">
<head>
<script src="js/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-controller="directiveCtrl">
<label>Geography</label><input type="text" ng-model="geography"/>
<br>
<div transclude-demo>
<button ng-click='showGeography()'>Show Geography</button>
and a link
</div>
</body>
</html>
app.js
angular.module('directivesApp', [])
.controller('directiveCtrl',function($scope){
$scope.showGeography=function(){alert('I am here');}
})
.directive('transcludeDemo',function(){
return{
transclude: true,
template: '<div ng-transclude> This is my directive content</div>',
link:function ($scope, element, attrs) { console.log('invoked in scope');}
}
});
I would have expected the transclude directive to replace/modify the contents of the div,with the contents of its template.
However,I find that the div is rendered as-is.
Is this how a transclude directive is expected to work?
Transclude is used to preserve the content that's already there, so if you just want to replace the content all you really need is the template. You're not seeing much in your example because your containing divs are essentially the same.
Replace content:
.directive('transcludeDemo',function(){
return{
template: '<div>This is my directive content</div>',
link:function ($scope, element, attrs) { console.log('invoked in scope');}
}
});
If you'd like to combine the new/old content in some way, add something in your template outside of the ng-transclude and it will render in combination.
Combine with transclude:
.directive('transcludeDemo',function(){
return{
transclude: true,
template: '<div>' +
'<p>This text will stay in tact</p>' +
'<div ng-transclude>This text will be replaced</div>' +
'</div>',
link:function ($scope, element, attrs) { console.log('invoked in scope');}
}
});
As mentioned in the comments, this second example should give you a better understanding of what's actually happening.

AngularJs transclude not working in Directive template or templateURL

I have written a custom directive like so, notice I have commented out the template URL that contains the same HTML structure and the template property:
.directive('sillyDirective', function ( ) {
'use strict';
return {
restrict: 'A',
replace: false,
transclude: true,
template: '<h2>Welcome to my site</h2>',
//templateUrl: '/views/hello.html' ,
link: function (scope, element, attrs) {
element.bind('click', function (){
alert('you click me! I am clicked');
});
};
});
In my HTML view I have the following...
<div data-silly-directive>
<div><img src="logo.jpg></div>
<div><h1>My First Website</h1></div>
</div>
The problem is the content of the directive, e.g.:
<div><img src="logo.jpg></div>
<div><h1>My First Website</h1></div>
is being overwritten with the template content even thought I have set transclude to true and replace to false? What am I doing wrong here?
you need to specify ng-transclude in the template of your directive, this will let angular know where to insert the content of the markup.
app.directive("foo", function() {
return {
transclude: true,
template: "<div>the template</div><div ng-transclude></div>"
};
})
html:
<div foo>
Some Content Here
</div>
result:
<div foo>
<div>the template</div>
<div ng-transclude>Some Content Here</div>
</div>
here's a plnkr
source: https://www.accelebrate.com/blog/angularjs-transclusion-part-1/
Your template must contain an element with an ng-transclude attribute. That's where the body will be "pasted" by angular.
See
https://docs.angularjs.org/api/ng/directive/ngTransclude

Put directive template as a content of container the directive is attached to

Normally, when i'm creating a directive, i have two possible ways to deal with directive templates. I can create a html file somewhere on my server and use it's URL in directive settings:
#directives.directive "someDirective", [
'$rootScope'
($rootScope) ->
controller: ($scope) ->
link: (scope, element, attrs) ->
return
restrict: 'A'
templateUrl: 'path/to/template.html'
scope: {
eventId: '#'
}
]
or i can put the script tag somewhere in the markup and use it's ID as a templateUrl:
<script type="text/ng-template" id="template.html">
<p>Hello {{ name }}</p>
</script>
However, i was wondering - is that possible to put that template to directive container tag as a body of it? That's how i want it to look:
<div my-ng-directive>
<p>Hello {{ name }}</p>
</div>
I think what you're looking for is ng-transclude,
basically ng-transclude allows your to "create" a slot in your original template that will contain the content of the original html element, so in your example a basic directive that does what you want will look like:
angular.module('myModule', [])
.directive('myNgDirective', function() {
return {
controller: function($scope) {
$scope.name = "Test";
},
transclude: true,
restrict: 'A',
template: '<div><h1>The directive</h1><div ng-transclude></div></div>'
}
});
This code:
<div my-ng-directive>
<p>Hello {{ name }}</p>
</div>
Will return:
<div>
<h1>The directive</h1>
<div>
<p>Hello {{ name }}</p>
</div>
</div>

Using ng-switch in directive with transclude

I am trying to create a template that shows some transcluded content. When I use ng-show everything works fine, but using ng-if or ng-switch gives me problems. I get this error message: Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found
I understand that ng-switch creates a new scope. But the transclude should still go up to the parent chain. Is this a defect in angularjs? See http://jsfiddle.net/HgvP7/
Here is my html, modified from the documentation example:
<div ng-app="docsTransclusionExample">
<div ng-controller="Ctrl">
<my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>
<!-- my-dialog.html -->
<script type="text/ng-template" id="my-dialog.html">
<div ng-switch="1+1">
<div ng-switch-when="2">
<div ng-transclude></div>
</div>
</div>
</script>
</div>
And the code:
angular.module('docsTransclusionExample', [])
.controller('Ctrl', function($scope) {
$scope.name = 'Tobias';
})
.directive('myDialog', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
templateUrl: 'my-dialog.html',
link: function (scope, element) {
scope.name = 'Jeff';
}
};
});

Resources