How to replace the element with ng-transclude
Solution 1
I think the best solution would probably be to create your own transclude-replace directive that would handle this. But for a quick and dirty solution to your example you could essentially manually place the result of the transclusion where you want:
my-transcluded-directive.html:
<div>
<span>I WILL BE REPLACED</span>
<div>I will not be touched.</div>
</div>
Directive:
return {
restrict:'A',
templateUrl:'templates/my-transcluded-directive.html',
transclude:true,
link:function(scope,element,attrs,ctrl, transclude)
{
element.find('span').replaceWith(transclude());
}
};
Solution 2
It's easy to create a ng-transclude-replace
directive, here is a copycat of the original ng-transclude
.
directive('ngTranscludeReplace', ['$log', function ($log) {
return {
terminal: true,
restrict: 'EA',
link: function ($scope, $element, $attr, ctrl, transclude) {
if (!transclude) {
$log.error('orphan',
'Illegal use of ngTranscludeReplace directive in the template! ' +
'No parent directive that requires a transclusion found. ');
return;
}
transclude(function (clone) {
if (clone.length) {
$element.replaceWith(clone);
}
else {
$element.remove();
}
});
}
};
}]);
PS:you can also check this link to see the difference between the ng-transclude
Solution 3
this works in Angular 1.4.9 (and prob earlier too)
return {
restrict: 'E',
replace: true,
template: '<span data-ng-transclude></span>',
transclude: true,
link: function (scope, el, attrs) .........
}
Solution 4
If you don't have to support IE and Edge you can use display:contents
in your css. That will destroy the wrapper on the level of css.
You can read more about this new display propertie here: https://css-tricks.com/get-ready-for-display-contents/
Current browser support (hope to see Edge support in the future): https://caniuse.com/#feat=css-display-contents
Francisc
Updated on June 06, 2020Comments
-
Francisc about 4 years
Is it possible to replace the element with
ng-transclude
on it rather than the entire template element?HTML:
<div my-transcluded-directive> <div>{{someData}}</div> </div>
Directive:
return { restrict:'A', templateUrl:'templates/my-transcluded-directive.html', transclude:true, link:function(scope,element,attrs) { } };
my-transcluded-directive.html:
<div> <div ng-transclude></div> <div>I will not be touched.</div> </div>
What I am looking for is a way to have
<div>{{someData}}</div>
replace<div ng-transclude></div>
. What currently happens is the transcluded HTML is placed inside theng-transclude
div element.Is that possible?
-
Belladonna over 9 yearsFor me
element
findsdiv[my-transcluded-directive]
, not the template. -
swehren over 9 years@LittleBigBot if you want to post a fiddle I'll take a look
-
Alex White over 9 yearsThank you! I've been searching for a viable solution that works with a directive that uses transclusion but is also a part of an ng-repeat. The accepted solution works but not with ng-repeat. I am thinking it has to do with
terminal: true
. The best part is that the user of this code doesn't have to know it for it to work :) -
fracz almost 9 yearsNote that you need to compile the contents if there are some directives:
.replaceWith($compile(transclude())(scope))
-
maow almost 9 yearsThanks. This
replace
trick won't work, if some child directive has dependency on the parent. -
Jon Onstott about 8 yearsAnother snippet of code that can help in some situations is
element.find('span').replaceWith(transclude().clone());
-
Roaders over 7 yearsBrilliant. Just what I wanted thank you very much. IMHO this should be the default behaviour for transclude rather than leaving empty, useless extra nesting Dom elements everywhere!
-
Simone Campagna about 5 years@Jonny Henry Briggs your fiddle doesn't appear to mantain "<div>I will not be touched.</div>" element. Your compiled doesn't report that element. So something is wrong :(