I am learning AngularJS.
I went through this video, here it shows putting ng-transclude on a tag in the template of directive, will append the already present DOM stuff in this tag.
Code :
<html ng-app="myApp">
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body ng-controller="AppCtrl">
<panel>
<button>Click Me</button>
</panel>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('AppCtrl', function() {
});
app.directive('panel', function() { //can return a function (link) or an object
return {
restrict: 'E',
transclude: true,
template: '<span> This is my custom span</span><div class="panel" ng-transclude>this is my div</div><span>Another span follows</span>'
}
});
</script>
</body>
</html>
Here's the fiddle, demonstrating the problem.
That is the normal behavior of the latest version.
From Angular API on ng-transclude.
"Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted."
If you run your fiddle with Angular version 1.0.8, then it will work like in the video.
Use a <span> as the transclusion host:
// Assign tpl var to template configuration property
var tpl = [
'<span> This is my custom span</span>',
'<div class="panel">',
'<span ng-transclude></span>',
' this is my div',
'</div>',
'<span ng-switch-when="divider"></span>',
'<span>Another span follows</span>'', // End
].join('\n');
Related
Angular directive is not working for the following case. In the my following angular application I have two kinds of item I wish to display which are stored in controller.
To display them I have created the directives for both cases, and iterating over list with ng-repeat, but the items are not being rendered.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<style media="screen">
.selected {
background: #cdcdcd;
}
</style>
</head>
<body ng-app="myApp">
<div ng-controller="ListController as listctrl">
<div class="" ng-repeat="item in listctrl.items">
<itemtype1 ng-if="item.type_ === 'type1'" val="item.val"></itemtype1>
<itemtype2 ng-if="item.type_ === 'type2'" val="item.val"></itemtype2>
</div>
</div>
<script type="text/javascript">
angular
.module('myApp',[])
.controller('ListController', function($scope) {
var listctrl = this;
listctrl.items = [];
listctrl.items.push({'val':'A', 'type_': 'type1'});
listctrl.items.push({'val':'B', 'type_': 'type2'});
listctrl.items.push({'val':'C', 'type_': 'type1'});
listctrl.items.push({'val':'D', 'type_': 'type2'});
})
.directive('itemtype1', function() {
return {
template: '<strong>{{$scope.val}}</strong>',
restrict: 'E',
scope: {
val: '='
},
link: function postLink(scope, element, attrs) {
}
};
})
.directive('itemtype2', function() {
return {
template: '<i>{{$scope.val}}</i>',
restrict: 'E',
scope: {
val: '='
},
link: function postLink(scope, element, attrs) {
}
};
});
</script>
</body>
</html>
My first guess, just glancing through it, is that you should change the following:
template: '<strong>{{$scope.val}}</strong>'
to this:
template: '<strong>{{val}}</strong>'
I'm trying to modify the input element using a custom AngularJS directive. Basically I want to replace any <input type="country"> fields with a country drop-down.
But the directive doesn't seem to work with input fields. If I change it to any other tag, it works?
Here is the code:
angular.module('plunker', [])
.controller('MainCtrl', function ($scope) {
$scope.name = 'World';
});
angular.module('plunker')
.directive('input', function() {
return {
restrict: 'E',
scope: {ngModel: '=?'},
link: function(scope, elem, attr) {
if(attr.type === 'country') {
elem.html('html code for select');
alert(elem);
}
}
};
});
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Name: <input type="country" ng-model="name"/> <br/>
</body>
</html>
Can someone please explain and suggest a workaround?
P.S. I've also tried doing this in the directive, but it doesn't work either!
replace: true,
template:'<div>hello</div>'
P.S. I know I can use a ng-country or some other custom tag but I want to change input tag only because I want learn why this is happening or possibly find out what I'm doing wrong?
Latest Update:
Your code is just setting the html on the element, instead of replacing it. You would want to use replaceWith instead like this:
var app = angular.module("TestApp",[]);
app.controller("TestController", function($scope){
$scope.message = "Input Directive Test"
});
app.directive("input", function() {
return {
restrict: "E",
link: function(scope, elem, attr) {
if(attr.type === "country") {
var select = angular.element("<select><option>USA</option></select>");
elem.replaceWith(select);
}
}
}
});
And here's the JSBin: https://jsbin.com/juxici/4/edit?html,js,output
Initial Version of my answer:
Here's an example that works without any issues when 'replace' and 'template' are used. I'm not checking for type and such, but you could do that in the linker code.
JSBin: https://jsbin.com/juxici/2/edit?html,js,output
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
</head>
<body ng-app="TestApp">
<div ng-controller="TestController">
<h2>{{message}}</h2>
<input type="country" ng-model="name"/>
</div>
</body>
</html>
Javascript:
var app = angular.module("TestApp",[]);
app.controller("TestController", function($scope){
$scope.message = "Input Directive Test"
});
app.directive("input", function() {
return {
restrict: "E",
replace: true,
template:"<select><option>USA</option></select>"
}
});
I am getting the error: angular.js:10627 Error: [$parse:syntax]
when interpolating a value in the template, only when it's in the attribute of an element.
template field_message.html:
<input type="number" ng-model="{{ model }}">
<div>{{ model }}</div>
directive:
myApp.directive('ivInput', function(){
return {
restrict: 'EA',
templateUrl: "field_message.html",
scope: {
model: '#ngModel'
}
};
});
view html:
<div iv-input="flatK" ng-model="modelname"></div>
In the template, the first instance of {{ model }} causes a parse error. If I remove this, the other instance correctly renders out the model name. Is there a way to get the model name into the value for ng-model on the input element?
Working absolutely fine.
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<meta charset="UTF-8">
</head>
<body ng-controller="ctrl">
<div iv-input="flatK" ng-model="modelname"></div>
<span>{{modelname}}</span>
<script>
var app = angular.module('app', []);
app.directive('ivInput', function(){
return {
restrict: 'EA',
template: "<input type='number' ng-model='ngModel'>"+
"<div>{{ model }}</div>",
scope: {
ngModel:'='
}
};
});
app.controller('ctrl',function($scope){
$scope.modelname=23;
} )
</script>
</body>
</html>
I am learning to create directives and made them available via dependency add, but somehow it is not working, let me know what I am doing wrong.
Plnkr - http://plnkr.co/edit/Mk4h7XvSN2YA26JZZ9Ua?p=preview
index.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<script src="https://code.angularjs.org/1.4.7/angular.js"></script>
<script type="text/javascript" src="firstDirective.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body ng-controller="mainCtrl as vm">
<div class="container">
<simple-directive></simple-directive>
</div>
</body>
</html>
firstDirective.js
angular
.module('firstdirective')
.directive('simpleDirective', function(){
return {
scope: true, // inherit child scope from parent
restrict: 'E',
replace: true,
template: '<h2>My first directive from dependency</h2>'
};
});
script.js
var myApp = angular.module('myApp', ['firstdirective']);
myApp.controller('mainCtrl', function(){
var vm = this;
})
To create a new module you need to pass an array of dependencies as the second argument:
angular.module('firstdirective', [])
Otherwise you are trying to retrieve the module.
I have an Angularjs script to create a navigation Bar using users parameters.
The problem is that, when i try to render the html structure, it always displays as plain text
This is the script:
var app = angular.module('userData', []);
app.controller('showUserData', ['$scope', function($scope){
$scope.userPar = JSON.parse(sessionStorage.userPar);
$scope.navBar = createNavBar($scope.userPar);
$scope.logOut = function(){
alert('Out you go!');
}
}]);
app.directive("otcNavbar", function(){
return {
template:"{{navBar}}"
};
});
function createNavBar(userPar){
var navBar = "<ul id=\"nav\">";
if(userPar.isDir == 1){
navBar +=
"<li class=\"seccion\">Director</li>";
}
if(userPar.isSys == 1){
navBar +=
"<li class=\"seccion\">System</li>";
}
navBar +=
"<li class=\"seccion\">Log Out</li></ul>";
return navBar;
}
This is the template:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link id="css" rel="stylesheet" href="main.css" type="text/css" />
<script src="angular.min.js"></script>
<script src="mainApp.js"></script>
</head>
<body>
<div id="userPar" ng-app="userData" ng-controller="showUserData">
<table id="sessionData">'.
<tr><th colspan="6">User Data</th></tr>'.
<tr><td class="R B">User No.:</td><td class="L">{{userPar.suID}}</td>.
<td class="R B">Name:</td><td class="L">{{userPar.sulName}}, {{userPar.sufName}}</td>.
<td class="R B">Access:</td><td class="L">{{userPar.utName}}</td></tr>
</table>
<!--<div id="navBar" otc-navbar></div>-->
<div id="navBar" ng-bind="navBar"></div>
</div>
</body>
</html>
I tried a directive (otc-navbar) and ng-bind, but in both cases i get plain text instead of html.
How can I make it work? Thanks in advance!
Use ng-bind-html with angular sanitize
<div id="navBar" ng-bind-html="navBar"></div>
ng-bind-html will evaluates your expression and inserts the resulting HTML into the element. By default, the resulting HTML content will be sanitized using the $sanitize service. In order to use ngSanitize, you need to include "angular-sanitize.js" in your application.
So include angular-sanitize.js in your page and inject the dependency to your angular module.
var app= angular.module('userData', ['ngSanitize']);
Here is a working sample on jsbin. :)
EDIT : As per the comment you wish ng-sanitize to not strip out the html attributes.
By default, ng-sanitize strips certain attributes out. If you really want that to not happen, You can use the $sce service's trustAsHtml method to explicitly tell angular that the markup you are passing is safe.
Here is a working sample