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.
This commit is contained in:
Luis Ramón López 2013-02-21 21:56:40 +01:00 committed by Igor Minar
parent 5e18a15fb0
commit eb53423a41
3 changed files with 76 additions and 3 deletions

View file

@ -406,10 +406,18 @@ compiler}. The attributes are:
migrates all of the attributes / classes from the old element to the new one. See the
{@link guide/directive#Components Creating Components} section below for more information.
You can specify `template` as a string representing the template or as a function which takes
two arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
a string value representing the template.
* `templateUrl` - Same as `template` but the template is loaded from the specified URL. Because
the template loading is asynchronous the compilation/linking is suspended until the template
is loaded.
You can specify `templateUrl` as a string representing the URL or as a function which takes two
arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
a string value representing the url.
* `replace` - if set to `true` then the template will replace the current element, rather than
append the template to the element.

View file

@ -652,9 +652,14 @@ function $CompileProvider($provide) {
}
}
if ((directiveValue = directive.template)) {
if (directive.template) {
assertNoDuplicate('template', templateDirective, directive, $compileNode);
templateDirective = directive;
directiveValue = (isFunction(directive.template))
? directive.template($compileNode, templateAttrs)
: directive.template;
directiveValue = denormalizeTemplate(directiveValue);
if (directive.replace) {
@ -977,11 +982,14 @@ function $CompileProvider($provide) {
// The fact that we have to copy and patch the directive seems wrong!
derivedSyncDirective = extend({}, origAsyncDirective, {
controller: null, templateUrl: null, transclude: null, scope: null
});
}),
templateUrl = (isFunction(origAsyncDirective.templateUrl))
? origAsyncDirective.templateUrl($compileNode, tAttrs)
: origAsyncDirective.templateUrl;
$compileNode.html('');
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
$http.get(templateUrl, {cache: $templateCache}).
success(function(content) {
var compileNode, tempTemplateAttrs, $template;

View file

@ -647,6 +647,32 @@ describe('$compile', function() {
});
describe('template as function', function() {
beforeEach(module(function() {
directive('myDirective', valueFn({
replace: true,
template: function($element, $attrs) {
expect($element.text()).toBe('original content');
expect($attrs.myDirective).toBe('some value');
return '<div id="templateContent">template content</div>';
},
compile: function($element, $attrs) {
expect($element.text()).toBe('template content');
expect($attrs.id).toBe('templateContent');
}
}));
}));
it('should evaluate `template` when defined as fn and use returned string as template', inject(
function($compile, $rootScope) {
element = $compile('<div my-directive="some value">original content<div>')($rootScope);
expect(element.text()).toEqual('template content');
}));
});
describe('templateUrl', function() {
beforeEach(module(
@ -1215,6 +1241,37 @@ describe('$compile', function() {
});
describe('template as function', function() {
beforeEach(module(function() {
directive('myDirective', valueFn({
replace: true,
templateUrl: function($element, $attrs) {
expect($element.text()).toBe('original content');
expect($attrs.myDirective).toBe('some value');
return 'my-directive.html';
},
compile: function($element, $attrs) {
expect($element.text()).toBe('template content');
expect($attrs.id).toBe('templateContent');
}
}));
}));
it('should evaluate `templateUrl` when defined as fn and use returned value as url', inject(
function($compile, $rootScope, $templateCache) {
$templateCache.put('my-directive.html', '<div id="templateContent">template content</span>');
element = $compile('<div my-directive="some value">original content<div>')($rootScope);
expect(element.text()).toEqual('');
$rootScope.$digest();
expect(element.text()).toEqual('template content');
}));
});
describe('scope', function() {
var iscope;