Angular directive as comment not working - angularjs

I'm referring AngularJS documentation, but couldn't get "Comment Directive" working the way its mentioned in fact encountered an error. Please find below details:
HTML:-
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script type="text/javascript" src="JS/DirectiveAsComment.js"></script>
<title>Directive as Comment</title>
</head>
<body ng-app="directiveAsCommentApp">
<!-- directive:test-comment-directive -->
</body>
</html>
JS:-
var app = angular.module('directiveAsCommentApp', []);
app.directive('testCommentDirective', function(){
return {
restrict: 'M',
replace: true,
template: 'this text is displayed because of "test-comment-directive" custom directive'
};
});
Error: [$compile:tplrt] Template for directive 'testCommentDirective' must have exactly one root element.
please help me solve this issue..

From the DOCs:
When a directive is declared with template (or templateUrl) and replace mode on, the template must have exactly one root element. That is, the text of the template property or the content referenced by the templateUrl must be contained within a single html element. For example, <p>blah <em>blah</em> blah</p> instead of simply blah <em>blah</em> blah. Otherwise, the replacement operation would result in a single element (the directive) being replaced with multiple elements or nodes, which is unsupported and not commonly needed in practice.
Please ref: https://docs.angularjs.org/error/$compile/tplrt
Change this
template: 'this text is displayed because of "test-comment-directive" custom directive'
to
template: '<div>this text is displayed because of "test-comment-directive" custom directive</div>'

The Problem is with your template, write them into some tags like or or :
try this
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"> </script>
<title>Directive as Comment</title>
</head>
<body ng-app="myApp">
<!-- directive:test-comment-directive -->
</body>
</html>
and in app.js try this
var app = angular.module('myApp', []);
app.directive('testCommentDirective', function(){
return {
restrict: "M",
replace: true,
template: "<div>this text is displayed because of 'test-comment-directive' custom directive</div>"
};
});

Related

Error: [$compile:tplrt] Template for directive must have exactly one root element

I know this question has been asked a bunch of times before, I read through the answers, tried the offered solutions, but I'm still getting the error and I'm not sure why. I stripped my application down to a simple hello world to try and figure out why its happening.
<!--index.html -->
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js"></script>
<script type="text/javascript"
src="./controller/MainController.ctrl.js"></script>
</head>
<body >
<div ng-controller="HelloController">
<test-dir/>
</div>
</body>
</html>
//controller/MainController.ctrl.js
var app = angular.module('app',[]);
app.controller("HelloController", function($scope) {
});
app.directive('testDir', function (){
return {
restrict:'E',
replace:true,
template:`template/helloWorld.template.html`
};
});
<!--template/helloWorld.template.html -->
<div>
<h1>hello, is it me you're looking for</h1>
</div>
if you are providing the link to the template file you should use templateUrl not template.
If you want to use template you have to write
"template":"<div>...</div>"
Change from template to templateUrl
`template:`template/helloWorld.template.html`
to
templateUrl :template/helloWorld.template.html

AngularJS Directive as a comment

I'm just playing with angular directives, but somehow the comment way to add directives is not showing up. Here is the markup.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="angular.js"></script>
</head>
<body ng-app="directive-app">
<first-directive></first-directive>
<div first-directive></div>
<div class=first-directive></div>
<!-- directive: first-directive -->
<script src="main.js"></script>
</body>
</html>
Directive definition
var app=angular.module('directive-app',[]);
app.directive("firstDirective", function() {
return {
restrict : "EACM",
templateUrl : 'template.html'
};
});
In template.html there is one h1 element. But comment way to add directives is not showing up in UI and in which case comment approach is even required.
Set replace option to true as follows
app.directive("firstDirective", function() {
return {
restrict: "EACM",
replace: true,
templateUrl: 'template.html'
};
});
Here's demo.

angular js dynamic directive passing model attribute

I knwo that are many relevant posts about how creating dynamic directive mapping in angular but I cannot find anything similar in my case. As the description suggests I am trying to make a dynamic directive where depending the value of an object attribute the html is changed. I simplified my problem to this case:
I have a list of object "Widget" which has an attribute name 'type'. I want depending on the type attribute of this list to render html depending on the attribute. To be more specific the Widget.type can have 3 values for example: widget1,widget2 . So in my case I want the directive to return the file widget*.html. (widget1.html for widget type "widget1" etc). Though I pass the argument to the directive using attributes, the value is not evaluated and the string widget.type is return.
Can you help me?
Thx in advance.
app.js file:
var app = angular.module("MainCtrl", []);
app.controller("myCtrl", function($scope) {
function Widget(type){
this.type=type;
}
$scope.widgets=[];
$scope.widgets.push(new Widget('widget1'),new Widget('widget2'),new Widget('widget3'));
});
app.directive('widget', function() {
return {
restrict: 'E',
scope: {
obj: '='
},
templateUrl: function(element,attr){
//console.log(attr);
console.log(attr.obj);
return attr.obj+'.html';
}
}
});
index.html file:
<!DOCTYPE html>
<html ng-app="MainCtrl">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<!-- css -->
<link rel="stylesheet" href="style.css" />
<!-- utilities -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<!-- angular module file -->
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl">
<div ng-repeat="widget in widgets">
{{widget.type}}
<widget obj='widget.type' ></widget>
</div>
</body>
widget1.html file:
<div class="widget">
widget1:{{widget.type}}
</div>
widget2.html,widget3.html are the same
Notice the console output in the directive.
I created a plunker so it's easier to notice the problem:http://plnkr.co/edit/ulBSQQrqpSV9g3BNGRhO?p=preview
First example with your directive: http://plnkr.co/edit/XAXy5RGLnvUZIoRj5xAs?p=preview
Secone example without your directive:
<div ng-repeat="widget in widgets">
<!--{{widget.type}}-->
<div ng-include="widget.template"></div>
</div>
Note: additional property in your Widget-object. Easier to handle.
First one is not as beautiful as the example without the directive, becaue your scope-variable of the directive has to be the same as the variable in your templates ('widget'). I like the second example much more.

ng-transclude in angular js

According to the definition of Transclusion in angular.js "With transclude enabled, anything that exists inside the welcome element in the view will be appended to the contents of whichever element in the template has the ng-transclude attribute.", I was trying to understand following behavior:-
<html>
<head>
<title>AngularJS Services</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
<script type="text/javascript" src="abc.js"></script>
</head>
<body ng-app="myApp">
<tab>
hello world
</tab>
</body>
</html>
Angular Code:-
var myApp=angular.module('myApp',[]);
function tab(){
return {
restrict : "E",
transclude: true,
template: '<h2 ng-transclude>Hello world!</h2>\
<div role="tabpanel" ng-transclude>kickass</div>',
scope: {},
link: function(scope,element,attrs){}
};
};
myApp.directive('tab',tab);
Now if u give ng-transclude inside h2 tag the contents under h2 are getting destroyed, however when I give ng-transclude in div it works fine. Transclusion here according to definition says that the values would be appended to anything between the tags. Please collect me if I am wrong.

How do I include HTML from an attribute as a token in a directive template

I want to inject HTML as an attribute into a template and have it display within the directive that passed the attribute.
My HTML
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-rc.0" src="https://code.angularjs.org/1.4.0-rc.0/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app">
<div>
<my-test mymessage='<b>Booya!</b>'></my-test>
</div>
</body>
</html>
My Javascript
app = angular.module('app', [])
.directive("myTest", function(){
return {
scope: {
mymessage: '='
},
restrict: 'E',
transclude: true,
template: '<p>Guess what...{{mymessage}}...you know it!</p>'
};
});
Here is the code in Plunker: http://plnkr.co/edit/ZJSkf1Ye4ccKURTJU8KD?p=preview
Note how it shows the literal for the binding.
I'm sure there are several problems here:
I am probably not properly binding the attribute within the directive scope
Once I have problem #1 solved I am pretty sure the HTML will be escaped.
What changes do I need to make in order to get the directive to render properly?
If you are binding HTML without Angular code (expressions and directives), then you need to use ng-bind-html:
scope: {
mymessage: "#" // no need for two-way binding
},
template: '<p>Guess what...<span ng-bind-html="mymessage"></span>...you know it!</p>'
This, on its own, would not work since it is unsafe. You have two options then:
1) include ngSanitize dependecy to your app:
angular.module("app", ["ngSanitize"])
This will automatically apply HTML sanitation - Demo
or, 2) use $sce service and call $sce.trustAsHtml on the variable holding the HTML content. This would not work, however with one-way string binding "#".

Resources