How to use the 'replace' feature for custom AngularJS directives?

AngularjsAngularjs Directive

Angularjs Problem Overview


Why does replace=true or replace=false not have any impact in the code below?

Why isn't the "some existing content" being displayed when replace=false?

Or putting it more humbly, can you kindly explain what is the replace=true/false feature in directives and how to use it?

Example

JS/Angular:

<script>
	angular.module('scopes', [])
		  .controller('Ctrl', function($scope) {
                $scope.title = "hello";

		  })
		  .directive('myDir', function() {
		    return {
		      restrict: 'E',
              replace: true,
			  template: '<div>{{title}}</div>'
		    };
	  });
</script>

HTML:

<div ng-controller="Ctrl">
	<my-dir><h3>some existing content</h3></my-dir>
</div>

See it in Plunker here:

http://plnkr.co/edit/4ywZGwfsKHLAoGL38vvW?p=preview

Angularjs Solutions


Solution 1 - Angularjs

When you have replace: true you get the following piece of DOM:

<div ng-controller="Ctrl" class="ng-scope">
    <div class="ng-binding">hello</div>
</div>

whereas, with replace: false you get this:

<div ng-controller="Ctrl" class="ng-scope">
    <my-dir>
        <div class="ng-binding">hello</div>
    </my-dir>
</div>

So the replace property in directives refer to whether the element to which the directive is being applied (<my-dir> in that case) should remain (replace: false) and the directive's template should be appended as its child,

OR

the element to which the directive is being applied should be replaced (replace: true) by the directive's template.

In both cases the element's (to which the directive is being applied) children will be lost. If you wanted to perserve the element's original content/children you would have to translude it. The following directive would do it:

.directive('myDir', function() {
    return {
        restrict: 'E',
        replace: false,
        transclude: true,
        template: '<div>{{title}}<div ng-transclude></div></div>'
    };
});

In that case if in the directive's template you have an element (or elements) with attribute ng-transclude, its content will be replaced by the element's (to which the directive is being applied) original content.

See example of translusion http://plnkr.co/edit/2DJQydBjgwj9vExLn3Ik?p=preview

See this to read more about translusion.

Solution 2 - Angularjs

replace:true is Deprecated

From the Docs:

>replace ([DEPRECATED!], will be removed in next major release - i.e. v2.0) > >specify what the template should replace. Defaults to false. > >- true - the template will replace the directive's element. >- false - the template will replace the contents of the directive's element.

-- AngularJS Comprehensive Directive API

From GitHub:

>Caitp-- It's deprecated because there are known, very silly problems with replace: true, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it".

-- AngularJS Issue #7636


Update

>Note: replace: true is deprecated and not recommended to use, mainly due to the issues listed here. It has been completely removed in the new Angular.

Issues with replace: true

For more information, see

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKaya ToastView Question on Stackoverflow
Solution 1 - AngularjskamilkpView Answer on Stackoverflow
Solution 2 - AngularjsgeorgeawgView Answer on Stackoverflow