aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Ramón López2013-02-21 21:56:40 +0100
committerIgor Minar2013-02-27 17:57:59 -0800
commiteb53423a41136fcda0c5e711f2d104952080354b (patch)
treef86eca5ac62d80a8f48af8da9ae26c58d194c477
parent5e18a15fb01d2e81adda68503754289fa9655082 (diff)
downloadangular.js-eb53423a41136fcda0c5e711f2d104952080354b.tar.bz2
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.
-rw-r--r--docs/content/guide/directive.ngdoc8
-rw-r--r--src/ng/compile.js14
-rw-r--r--test/ng/compileSpec.js57
3 files changed, 76 insertions, 3 deletions
diff --git a/docs/content/guide/directive.ngdoc b/docs/content/guide/directive.ngdoc
index 59b89b40..2253ea30 100644
--- a/docs/content/guide/directive.ngdoc
+++ b/docs/content/guide/directive.ngdoc
@@ -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.
diff --git a/src/ng/compile.js b/src/ng/compile.js
index 3746bb66..c04d3871 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -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;
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 6f56c6e6..f81199cb 100644
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -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;