AngularJS Directive’s replace option can be used to replace the container element itself by directive content. By default, the directive content inserted as the child of the element directive is applied on. But using replace, that container element altogether can be replaced by directive’s actual content HTML.
Let’s understand this with help of few examples. Below is the live application from previous example:
Live Example:
If you inspect each item of this demo-example in Developer tools of your browser, you will find something like this:
<div ng-repeat="bla in ctrl.items" class="ng-scope"> <item-widget item="bla" promo="Christmas-Sale" on-select="ctrl.onItemSelect(selectedItem)" class="ng-isolate-scope"> <div class="panel panel-default"> <div class="panel-heading ng-binding"> Published at:<span ng-bind="item.published | date" class="ng-binding">01/11/2015</span> Promotion: Christmas-Sale<button class="pull-right" ng-click="pickMe({selectedItem:item.name})">Buy me</button> </div> <div class="panel-body"> Name:<span ng-bind="item.name" class="ng-binding">Computer</span> Condition:<span ng-bind="item.condition" class="ng-binding">New</span> Price:<span ng-bind="item.price | currency" class="ng-binding">$500.00</span> Brand:<span ng-bind="item.brand" class="ng-binding">Lenovo</span> </div> </div> </item-widget> </div>
You can see that there is an item-widget element for each item [or a specific ‘div’ if item-widget were used as an attribute of that div].
Whenever AngularJS encounters a directive, it fetches the content of that directive and insert it as a child of the element the directive was applied on. In this case it is the item-widget element itself. This is the default behavior. But sometimes, you may prefer the original element [ the directive is applied on] to be completely replaced by directive content.
AngularJS provides replace
key as part of directive definition. It’s default value is false, means the container element will remain there. By setting it to true, you can replace the container element by actual content of directive. All attributes of the container element will then be migrated on the top level element in directive content.
Let’s add replace key in previous example, like shown below:
.directive('itemWidget', [function() { return{ replace:true, ....//other elements as in above example. }]);
Live Example using replace option:
Now if you check each item in Developer tools, you will find following content:
<div ng-repeat="bla in ctrl.items" class="ng-scope"> <div class="panel panel-default ng-isolate-scope" item="bla" promo="Christmas-Sale" on-select="ctrl.onItemSelect(selectedItem)"> <div class="panel-heading ng-binding"> Published at:<span ng-bind="item.published | date" class="ng-binding">01/11/2015</span> Promotion: Christmas-Sale<button class="pull-right" ng-click="pickMe({selectedItem:item.name})">Buy me</button> </div> <div class="panel-body"> Name:<span ng-bind="item.name" class="ng-binding">Computer</span> Condition:<span ng-bind="item.condition" class="ng-binding">New</span> Price:<span ng-bind="item.price | currency" class="ng-binding">$500.00</span> Brand:<span ng-bind="item.brand" class="ng-binding">Lenovo</span> </div> </div> </div>
The <item-widget> element is removed altogether , and all it’s attributes are migrated to top level div of actual content.
Remark: If you see carefully in developer tools, you will find that <div ng-repeat=”bla in ctrl.items” class=”ng-scope”> itself is repeated for each item. This is because for ng-repeat directive, the replace key is false.
Complete Code:
<html> <head> <title>Directive Demo</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/> </head> <body class="jumbotron container" ng-app="myApp"> <div ng-controller="AppController as ctrl"> <h3>List of Sale Items.</h3> <div ng-repeat="bla in ctrl.items"> <item-widget item="bla" promo="Christmas-Sale" on-select="ctrl.onItemSelect(selectedItem)"></item-widget> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"> </script> <script> angular.module('myApp', []) .controller('AppController', [function() { var self = this; self.items = [ {name: 'Computer', price: 500, condition:'New',brand : 'Lenovo', published:'01/11/2015'}, {name: 'Phone', price: 200, condition:'New',brand : 'Samsung', published:'02/11/2015'}, {name: 'Printer', price: 300, condition:'New',brand : 'Brother', published:'06/11/2015'}, {name: 'Dishwasher', price: 250, condition:'Second-Hand',brand : 'WhirlPool', published:'01/12/2015'}, ]; self.onItemSelect = function(name) { console.log('Congrats. You have just bought a', name); }; }]) .directive('itemWidget', [function() { return{ restrict: 'E', replace:true, scope: { item: '=', promo: '@', pickMe : '&onSelect' }, templateUrl: 'saleItem3.html', link : function(scope, element, attrs){ //Add event listener for 'click' event element.on('click', function(event) { element.html('Thanks for buying this item.'); element.css({ color: 'green' }); }); } } }]); </script> </body> </html>
Shown below is the directive’s content[saleItem3.html].
<div class="panel panel-default"> <div class="panel-heading"> Published at:<span ng-bind="item.published | date"></span> Promotion: {{promo}}<button class="pull-right" ng-click="pickMe({selectedItem:item.name})">Buy me</button> </div> <div class="panel-body"> Name:<span ng-bind="item.name"></span> Condition:<span ng-bind="item.condition"></span> Price:<span ng-bind="item.price | currency"></span> Brand:<span ng-bind="item.brand"></span> </div> </div>
That’s it for replace option. Let’s move to next configuration option [transclude with ngTransclude
] of Directive Definition Object, which can be used to create directive that wraps other elements.
You can use popular Apache HTTP server to serve files. If you need assistance setting-up server,
this post can help you.
References
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…