Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit eb53423

Browse files
lrlopezIgorMinar
authored andcommitted
feat($compile): support for dynamic template generation
`template` and `templateUrl` properties can now be optionally defined via a function. This allows templates to be dynamically generated on the fly.
1 parent 5e18a15 commit eb53423

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

docs/content/guide/directive.ngdoc

+8
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,18 @@ compiler}. The attributes are:
406406
migrates all of the attributes / classes from the old element to the new one. See the
407407
{@link guide/directive#Components Creating Components} section below for more information.
408408

409+
You can specify `template` as a string representing the template or as a function which takes
410+
two arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
411+
a string value representing the template.
412+
409413
* `templateUrl` - Same as `template` but the template is loaded from the specified URL. Because
410414
the template loading is asynchronous the compilation/linking is suspended until the template
411415
is loaded.
412416

417+
You can specify `templateUrl` as a string representing the URL or as a function which takes two
418+
arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
419+
a string value representing the url.
420+
413421
* `replace` - if set to `true` then the template will replace the current element, rather than
414422
append the template to the element.
415423

src/ng/compile.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,14 @@ function $CompileProvider($provide) {
652652
}
653653
}
654654

655-
if ((directiveValue = directive.template)) {
655+
if (directive.template) {
656656
assertNoDuplicate('template', templateDirective, directive, $compileNode);
657657
templateDirective = directive;
658+
659+
directiveValue = (isFunction(directive.template))
660+
? directive.template($compileNode, templateAttrs)
661+
: directive.template;
662+
658663
directiveValue = denormalizeTemplate(directiveValue);
659664

660665
if (directive.replace) {
@@ -977,11 +982,14 @@ function $CompileProvider($provide) {
977982
// The fact that we have to copy and patch the directive seems wrong!
978983
derivedSyncDirective = extend({}, origAsyncDirective, {
979984
controller: null, templateUrl: null, transclude: null, scope: null
980-
});
985+
}),
986+
templateUrl = (isFunction(origAsyncDirective.templateUrl))
987+
? origAsyncDirective.templateUrl($compileNode, tAttrs)
988+
: origAsyncDirective.templateUrl;
981989

982990
$compileNode.html('');
983991

984-
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
992+
$http.get(templateUrl, {cache: $templateCache}).
985993
success(function(content) {
986994
var compileNode, tempTemplateAttrs, $template;
987995

test/ng/compileSpec.js

+57
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,32 @@ describe('$compile', function() {
647647
});
648648

649649

650+
describe('template as function', function() {
651+
652+
beforeEach(module(function() {
653+
directive('myDirective', valueFn({
654+
replace: true,
655+
template: function($element, $attrs) {
656+
expect($element.text()).toBe('original content');
657+
expect($attrs.myDirective).toBe('some value');
658+
return '<div id="templateContent">template content</div>';
659+
},
660+
compile: function($element, $attrs) {
661+
expect($element.text()).toBe('template content');
662+
expect($attrs.id).toBe('templateContent');
663+
}
664+
}));
665+
}));
666+
667+
668+
it('should evaluate `template` when defined as fn and use returned string as template', inject(
669+
function($compile, $rootScope) {
670+
element = $compile('<div my-directive="some value">original content<div>')($rootScope);
671+
expect(element.text()).toEqual('template content');
672+
}));
673+
});
674+
675+
650676
describe('templateUrl', function() {
651677

652678
beforeEach(module(
@@ -1215,6 +1241,37 @@ describe('$compile', function() {
12151241
});
12161242

12171243

1244+
describe('template as function', function() {
1245+
1246+
beforeEach(module(function() {
1247+
directive('myDirective', valueFn({
1248+
replace: true,
1249+
templateUrl: function($element, $attrs) {
1250+
expect($element.text()).toBe('original content');
1251+
expect($attrs.myDirective).toBe('some value');
1252+
return 'my-directive.html';
1253+
},
1254+
compile: function($element, $attrs) {
1255+
expect($element.text()).toBe('template content');
1256+
expect($attrs.id).toBe('templateContent');
1257+
}
1258+
}));
1259+
}));
1260+
1261+
1262+
it('should evaluate `templateUrl` when defined as fn and use returned value as url', inject(
1263+
function($compile, $rootScope, $templateCache) {
1264+
$templateCache.put('my-directive.html', '<div id="templateContent">template content</span>');
1265+
element = $compile('<div my-directive="some value">original content<div>')($rootScope);
1266+
expect(element.text()).toEqual('');
1267+
1268+
$rootScope.$digest();
1269+
1270+
expect(element.text()).toEqual('template content');
1271+
}));
1272+
});
1273+
1274+
12181275
describe('scope', function() {
12191276
var iscope;
12201277

0 commit comments

Comments
 (0)