In angular JS, we have a property called replace with possible values as true or false while defining directive. But i dont understand how this property will be used. Will it replace the HTML parent element when it is set true
Actual template:
<div class="parent">
<my-dir><div>Hello world!!</div></my-dir>
</div>
if replace is true, mir-dir tag will be removed.
<div class="parent">
<div>Hello world!!</div>
</div>
if replace is false, mir-dir tag will not be removed.
<div class="parent">
<my-dir><div>Hello world!!</div></my-dir>
</div>
Hope you understand!!. let me know if you have any queries.
Replace - If set to true will replace the element having a directive on it with a template.
PS : You have to use templateUrl/template along with replace.
HTML
<div angular></div>
<div class="angular"></div>
<angular>Simple angular directive</angular>
JS
var App = angular.module('App', []);
App.directive('angular', function() {
return {
restrict: 'ECMA',
replace: true,
template: '<img src="http://goo.gl/ceZGf"/>'
};
});
Above example angular directive will replace its contents "Simple angular directive" by contents in template i.e "Replaced content".
According to the documentation of angular (replace option):
true - the template will replace the directive's element.
false - the template will replace the contents of the directive's element.
Imagine you have a directive named my-directive with the template <span>directive</span> and your html code is <div my-directive></div>. Then replace : false results in:
<div my-directive><span class="replaced" my-directive="">directive</span></div>
And replace : true results in:
<span class="replaced" my-directive="">directive</span>
Please note that this option is deprecated.
See related questions:
How to use `replace` of directive definition?
Explain replace=true in Angular Directives (Deprecated)
Related
Use case:
In my index.html. I have two ng-include directives and two custom directives.
Each directive has its src attribute defined the address to load some html snippet from another server (the custom directives have its template attribute loading the html)
I need to make sure that all directives (see the code 1,2,3) have fully loaded the html snippets before I call the fifth ng-include directive (4) to load the java-script from another server.
Right now all directives are running asynchronously and I can't be sure that the directive which loads the Javascript should always be the last one to load. I need this because if Javascript is loaded and executed before the html it wouldn't go through the html and linking it to javascript/jQuery.
I have solved this issue using a very classic way. I update a global variable whenever the html snipts are loaded and define the an ng-include directive to load the Javascript conditionally when the global variable is true indicating all other directives have loaded their html. But this is not the Angular way. I need the Angular way and btw I'm new starter on Angular.
Index.html
<div ng-controller="navigationController" >
**(1)**<agilesites-navbar></agilesites-navbar>
<div class="container-fluid">
<div class="row row-offcanvas row-offcanvas-right">
<div id="offcanvas-curtain" class="hidden-lg"></div>
<div id="contentContainer" class="col-sm-12 col-md-12 col-lg-12">
<div ui-view="content" id="content"></div>
</div>
**(2)**<agilesites-sidebar></agilesites-sidebar>
</div>
</div>
**(3)**<ng-include src="''+API_HOST+'api/cms/footer'" onload="cmsResourceLoadingStatus(true)"></ng-include>
**(4)**<ng-include src="''+API_HOST+'api/cms/javascript'" ng-if="cmsResourceLoadingCompleted"></ng-include>
</div>
Custom directive (agilesites-sidebar):
angular.module('newhorizonsApp')
.directive('agilesitesSidebar', ['ProductTypes','$compile', function (ProductTypes,$compile) {
return {
restrict: 'E',
scope: true,
template: '<ng-include src="\'\'+API_HOST+\'api/cms/sidebar\'" onload="executeOnLoad();"></ng-include>',
link: function (scope,elem){
scope.executeOnLoad = function() {
scope.cmsResourceLoadingStatus(true);
};
}
};
}]);
I am creating an angular.js application.
I have written a html page and wants to put it under div using directive
<div data-(<directive-name)>
</div>
DxPDictionary.directive('import', [function () {
return {
restrict: 'A',
templateUrl: 'template/Import.html',
scope: false,
}
It's not working, is this approch is right or should use another way to achieve this
<body ng-controller="userCtrl">
<div class="container">
<div ng-include="'myUsersList.html'"></div>
<div ng-include="'myUsersForm.html'"></div>
</div>
</body>
use like this.
<div data-directive-name>
</div>
DxPDictionary.directive('dataDirectiveName', [function () {
return {
restrict: 'A',
templateUrl: 'template/Import.html',
scope: false,
}
your directive name dataDirectiveName in directive definition in camel case format and directive name data-directive-name on DOM should match.
You can use ng-include if you are not creating reusable components using directive and want use is as only html of the page.
There is already a directive for this purpose. You do not need to create your own.
https://docs.angularjs.org/api/ng/directive/ngBindHtml
Ashley's answer is good if you keep your html in a file. If you dynamically generate your html, you can use ng-bind-html directive.
Can somebody explains what means:
replace: true / false
and
transclude: true / false
in an angularjs directive?
I did read the documentation but could understand it 100%.
Replace
Whenever you say replace: true, you are telling your directive to replace your directive tag with the template of directive.
Assume you have used template: '<div>This is directive template</div>' in your directive that look like <div data-my-directive></div> When you run your application all the directives div in DOM will be replaced by <div>This is directive template</div>
However in the same scenario if you declare replace: false Your DOM will have something like this
<div data-my-directive>
<div>This is directive template</div>
</div>
TRANSCLUDE
You use ng-transclude, you want to append data in the directive template from controller of your view.
Lets say you have template in your directive which looks like
template: '<div class="main"><div data-ng-transclude></div></div>'
So when you set transclude: true you are explicitly telling your directive to allow all the transcluded values to be part of directive itself when DOM loads.
Lets say you have used the directive in your view like this:
<div data-my-directive>
Transcluded data
</div>
You will see th the text Transcluded data in your web page, however if you have set transclude: false You wont see the text Transcluded data
To keep it simple:
Replace true will replace your directive's template with the tag from where you called your directive:
<my-directive></my-directive>
if replace is true will become:
<div>bla bla</div>
if replace is false will become:
<my-directive><div>bla bla</div></my-directive>
Transclude will "copy" whatever is inside your directive, and append it somewhere on your template:
<my-directive>This is some content</my-directive>
if transclude is true:
<my-directive>
<div>bla bla</div>
<span>This is some content</span> <!--for this to work your template needs to use the ng-transclude directive -->
</my-directive>
if transclude is false:
<my-directive>
<div>bla bla</div>
</my-directive>
My html:
<div ng-app="myApp">
<div ng-controller="testCtrl">
<div in-tags text="{{ tags }}"></div>
<div data-ng-show="tags.length" in-tags text="{{ tags }}"></div>
<p data-ng-show="tags.length">another text</p>
</div>
</div>
And js:
.controller('testCtrl', function($scope){
$scope.tags = 'one two three';
})
.directive( 'inTags',function() {
return {
scope: {
text: '#'
},
template: '<span ng-repeat="item in text | splitByWords"> {{ item }} </span>'
};
})
.filter( 'splitByWords', function() {
return function( text ) {
return text.split( /\s+/ );
};
});
How it works: http://jsfiddle.net/3HT2F/12/
Question is: Why tags.length interpreted like false with directive?
extra question: How can i hide div?
For your primary question, the scope attribute on your directive (inTags) sets a new isolated scope with only one member (the connected text attribute). It's one of the stumbling blocks of Angular with nested scopes and isolated scopes. When you set a literal object for the scope and specify a mapping (such as this case with at the dom attribute binding using '#'), it creates an isolated scope that doesn't inherit any other values from its parent. So tags is no longer a member of the local scope on that element.
See the scope rules for directives
Second question, why wouldn't ngShow or ngHide work? If you're on a new enough Angular (1.2+), you can also use ngIf to complete remove elements vs just hiding them.
Edit: Here's your fiddle updated
When should I use transclude: 'true' and when transclude: 'element' ?
I cant find anything about transclude: 'element' in the angular docs, they are pretty confusing.
I would be happy if someone could explain this in simple language.
What is the benefit of each option? What is the real difference between them?
This is what I have found :
transclude: true
Inside a compile function, you can manipulate the DOM with the help of transclude linking function or you can insert the transcluded DOM into the template using ngTransclude directive on any HTML tag.
and
transclude: ‘element’
This transcludes the entire element and a transclude linking function is introduced in the compile function. You can not have access to scope here because the scope is not yet created. Compile function creates a link function for the directive which has access to scope and transcludeFn lets you touch the cloned element (which was transcluded) for DOM manipulation or make use of data bound to scope in it. For your information, this is used in ng-repeat and ng-switch.
From AngularJS Documentation on Directives:
transclude - compile the content of the element and make it available to the directive. Typically used with ngTransclude. The advantage of transclusion is that the linking function receives a transclusion function which is pre-bound to the correct scope. In a typical setup the widget creates an isolate scope, but the transclusion is not a child, but a sibling of the isolate scope. This makes it possible for the widget to have private state, and the transclusion to be bound to the parent (pre-isolate) scope.
true - transclude the content of the directive.
'element' - transclude the whole element including any directives defined at lower priority.
transclude: true
So let's say you have a directive called my-transclude-true declared with transclude: true that looks like this:
<div>
<my-transclude-true>
<span>{{ something }}</span>
{{ otherThing }}
</my-transclude-true>
</div>
After compiling and before linking this becomes:
<div>
<my-transclude-true>
<!-- transcluded -->
</my-transclude-true>
</div>
The content (children) of my-transclude-true which is <span>{{ something }}</span> {{..., is transcluded and available to the directive.
transclude: 'element'
If you have a directive called my-transclude-element declared with transclude: 'element' that looks like this:
<div>
<my-transclude-element>
<span>{{ something }}</span>
{{ otherThing }}
</my-transclude-element>
</div>
After compiling and before linking this becomes:
<div>
<!-- transcluded -->
</div>
Here, the whole element including its children are transcluded and made available to the directive.
What happens after linking?
That's up to your directive to do what it needs to do with the transclude function. ngRepeat uses transclude: 'element' so that it can repeat the whole element and its children when the scope changes. However, if you only need to replace the tag and want to retain it's contents, you can use transclude: true with the ngTransclude directive which does this for you.
When set to true, the
directive will delete the original content, but make it available for reinsertion within
your template through a directive called ng-transclude.
appModule.directive('directiveName', function() {
return {
template: '<div>Hello there <span ng-transclude></span></div>',
transclude: true
};
});
<div directive-name>world</div>
browser render: “Hello there world.”
The best way of think about transclusion is a Picture Frame.A picture frame has its own design and a space for adding the picture.We can decide what picture will go inside of it.
When it comes to angular we have some kind of controller with its scope and inside of that we will place a directive that supports transclusion. This directive will have it’s own display and functionality . In non-transluded directive, content inside the directive is decided by the directive itself but with transclusion,just like a picture frame,we can decide what will be inside the directive.
angular.module("app").directive('myFrame', function () {
return {
restrict: 'E',
templateUrl:"frame.html",
controller:function($scope){
$scope.hidden=false;
$scope.close=function(){
$scope.hidden=true;
}
},
transclude:true
}
});
Content inside the directive
<div class="well" style="width:350px;" ng-hide="hidden">
<div style="float:right;margin-top:-15px">
<i class="glyphicon glyphicon-remove" ng-click="close()" style="cursor:pointer"></i>
</div>
<div ng-transclude>
/*frame content goes here*/
</div>
</div>
Call Directive
<body ng-controller="appController">
<my-frame>
<span>My Frame content</span>
</my-frame>
</body>
Example