How to use defined text/ng-template in AngularJS directive
Solution 1
Looking at your directive i can suggest try ng-include
. Where you want to do
//$compile(ComboboxDropdownTemplate) +
'</div>'
change it to
<span ng-include='templateUrlPropertyOnScope'>
'</div>'
templateUrlPropertyOnScope
property should point to a template either on server side or in script section created with type=text/ng-template
.
Solution 2
HTML
<script type="text/ng-template" id="myDirectivesCustomTemplate.html">
<ul>
<li ng-repeat="value in values">
<a ng-click="doSomething({id:value.id})">
{{value.name}}
</a>
</li>
</ul>
</script>
<div ng-controller="MainCtrl">
<div my-directive template="myDirectivesCustomTemplate.html" mydata="mydata" mycallback="doSomething(id)"></div>
</div>
JS
app.controller('MainCtrl',function($scope){
$scope.mydata = [{id:1,name:'One'},{id:2,name:'Two'},{id:3,name:'Three'}];
$scope.doSomething = function(id){
alert(id);
}
});
app.directive('myDirective', function($templateCache,$compile) {
return {
restrict: 'A',
scope:{
template : "@",
mydata : "=",
mycallback:"&"
},
link: function(scope,element) {
var template = $templateCache.get(scope.template);
scope.values = scope.mydata;
scope.doSomething = scope.mycallback;
element.append($compile(template)(scope));
}
}
});
Solution 3
I know this is 4 years later but if anyone still has this question, perhaps this answer may also be found useful.
With a simple directive such as this:
<my-directive template="custom-template.html"></my-directive>
You can then refer to the template attribute in your directive, like this:
(function() {
angular
.module('app')
.directive('myDirective', myDirective);
function myDirective() {
return {
restrict: 'E',
templateUrl: function(elem, attrs) {
return attrs.template;
}
}
}
}
Solution 4
you can use $http
and $compile
to achieve such a task.
app.directive('myDirective', function($http, $templateCache, $compile) {
return {
scope: {
// reference to your data.
// Just use `data.values` or `data.whatever` in your template
data: '=myDirectiveData'
},
link: function(scope, elm, attrs) {
// Load the template via my-directive-custom-template attribute
$http.get(attrs.myDirectiveCustomTemplate, {cache: $templateCache}).success(function(html) {
// update the HTML
elm.html(html);
// compile the html against the scope
return $compile(elm.contents())(scope);
});
}
};
});
I hope it gives you a good start
Andresch Serj
Senior Full-Stack Developer that loves Angular/Typescript/NestJs and Bicycles. Loves Test Driven, Domain Driven, Component Driven and even Behaviour Driven. Loves T-Shaped Teams.
Updated on August 18, 2020Comments
-
Andresch Serj almost 4 years
I try to write a very flexible directive. For doing so i want the user to define a template used in part of my return (as seen in the ui-bootstrap typeahead directive).
So i define my template like this:
<script type="text/ng-template" id="myDirectivesCustomTemplate.html"> <ul> <li ng-repeat="value in values"> <a ng-click="doSomething(value.id)"> {{value.name}} </a> </li> </ul> </script>
I set this template in my directive
<div my-directive my-directive-custom-template="myDirectivesCustomTemplate.html" my-directive-data="someScopeData">
Now in my directive, how can i render the custom template and use it with the passed data? When i try to use it to return in template directly it throws a
ReferenceError: $scope is not defined
Error. If i call it without scope, it saysReferenceError: myDirectiveCustomTemplate is not defined
Error.Where and how can i use my template if i do not just want to use it as a return directly?
EDIT: let's say, this is my directive:
(function() { 'use strict'; var Combobox = function() { var displayInputField = elem.find('input.dropdown'); scope.$watch(scope.nsdComboboxModel,function(newVal){ /* search for newVal in given data object */ scope.setDisplayInputValue(newVal); }); scope.setDisplayInputValue = function(value) { displayInputField.val(value); }; scope.elementSelected = function (item, model, label) { scope.ComboboxCallback(item); scope.setDisplayInputValue(label); }; } return { restrict: 'A', transclude: true, scope: { Combobox: '@', /* used as HTML/CSS-id/name/path */ ComboboxModel: '=', /* the actual AngularJS model (ng-model) */ ComboboxAutocompleteData: '=', /* the data used for autoComplete (must be array of objects having id and value) */ ComboboxDropdownData: '=', /* data used by the dropdown template */ ComboboxCallback: '=', /* a callback function called with selected autocomplete data item on select */ ComboboxLabel: '@', /* label for the input field */ ComboboxDropdownTemplate: '@' /* label for the input field */ }, template: '<section class="-combobox-directive container-fluid">' + '<label for="{{Combobox}}" ng-if="ComboboxTranslation" translate="{{ComboboxLabel}}"></label>' + '<div class="combobox input-group">' + '<input type="text" ' + 'id="{{Combobox}}" ' + 'autocomplete="off" ' + 'ng-model="ComboboxDestinationDisplay" ' + 'data-toggle="dropdown" ' + 'typeahead="value as location.value for location in ComboboxAutocompleteData | filter:$viewValue" ' + 'typeahead-editable="false" ' + 'typeahead-on-select="elementSelected($item, $model, $label)" ' + 'class="form-control dropdown">' + // dropdown-toggle '<span data-toggle="dropdown" class="input-group-addon dropdown-toggle">' + '<span class="glyphicon glyphicon-globe"></span>' + '</span>' + //$compile(ComboboxDropdownTemplate) + '</div>' + '</section>', link: link }; }; angular.module('vibe.directives').directive('nsdCombobox', [NsdCombobox]); })();