Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit df1e271

Browse files
committed
feat($compile): Allow using functions as templates in directives
Added dynamic template support in directives: - The call will pass the element and directive attributes as parameters - This allows generating templates on the fly - It also applies to templateUrl
1 parent c38c1c5 commit df1e271

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

docs/content/guide/directive.ngdoc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,14 @@ compiler}. The attributes are:
380380
* `template` - replace the current element with the contents of the HTML. The replacement process
381381
migrates all of the attributes / classes from the old element to the new one. See the
382382
{@link guide/directive#Components Creating Components} section below for more information.
383+
If the template is a function, it will be called with the current elementa normalized list of
384+
attributes (see {@link guide/directive#Attributes Attributes}). The content returned by the
385+
call will be the template to be compiled.
383386

384387
* `templateUrl` - Same as `template` but the template is loaded from the specified URL. Because
385388
the template loading is asynchronous the compilation/linking is suspended until the template
386-
is loaded.
389+
is loaded. You can also use a function that will return the URL to load. The call will include
390+
the current element and the normalized list of attributes as a single parameter.
387391

388392
* `replace` - if set to `true` then the template will replace the current element, rather than
389393
append the template to the element.

src/ng/compile.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,9 @@ function $CompileProvider($provide) {
649649
if ((directiveValue = directive.template)) {
650650
assertNoDuplicate('template', templateDirective, directive, $compileNode);
651651
templateDirective = directive;
652+
if (isFunction(directive.template)) {
653+
directiveValue = directive.template($compileNode, templateAttrs);
654+
}
652655
directiveValue = denormalizeTemplate(directiveValue);
653656

654657
if (directive.replace) {
@@ -971,11 +974,19 @@ function $CompileProvider($provide) {
971974
// The fact that we have to copy and patch the directive seems wrong!
972975
derivedSyncDirective = extend({}, origAsyncDirective, {
973976
controller: null, templateUrl: null, transclude: null, scope: null
974-
});
977+
}),
978+
urlToLoad;
975979

976980
$compileNode.html('');
977981

978-
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
982+
if (isFunction(origAsyncDirective.templateUrl)) {
983+
urlToLoad = origAsyncDirective.templateUrl($compileNode, tAttrs);
984+
}
985+
else {
986+
urlToLoad = origAsyncDirective.templateUrl;
987+
}
988+
989+
$http.get(urlToLoad, {cache: $templateCache}).
979990
success(function(content) {
980991
var compileNode, tempTemplateAttrs, $template;
981992

test/ng/compileSpec.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,49 @@ describe('$compile', function() {
647647
});
648648

649649

650+
describe('template function', function() {
651+
652+
beforeEach(module(function() {
653+
directive('replace', valueFn({
654+
replace: true,
655+
template: function(e,f) {
656+
return '<div class="log" style="width: 10px" high-log>Replace!</div>'
657+
},
658+
compile: function(element, attr) {
659+
attr.$set('compiled', 'COMPILED');
660+
expect(element).toBe(attr.$$element);
661+
}
662+
}));
663+
664+
directive('replaceattr', valueFn({
665+
replace: true,
666+
template: function(e, f) {
667+
expect(e.text()).toBe('ignore');
668+
return '<div class="log" style="width: 10px" high-log ' + f.myattr + '="123">Replace!</div>'
669+
},
670+
compile: function(element, attr) {
671+
expect(element.text()).toBe('Replace!');
672+
expect(attr.dynamic).toBe('123');
673+
attr.$set('dynamic', '456');
674+
}
675+
}));
676+
}));
677+
678+
679+
it('should replace element with template returned by function', inject(function($compile, $rootScope) {
680+
element = $compile('<div><div replace>ignore</div><div>')($rootScope);
681+
expect(element.text()).toEqual('Replace!');
682+
expect(element.find('div').attr('compiled')).toBe('COMPILED');
683+
}));
684+
685+
it('should pass element and attributes to template function', inject(function($compile, $rootScope) {
686+
element = $compile('<div><div replaceattr myattr="dynamic">ignore</div><div>')($rootScope);
687+
expect(element.text()).toEqual('Replace!');
688+
expect(element.find('div').attr('dynamic')).toBe('456');
689+
}));
690+
});
691+
692+
650693
describe('templateUrl', function() {
651694

652695
beforeEach(module(
@@ -1214,6 +1257,59 @@ describe('$compile', function() {
12141257
});
12151258
});
12161259

1260+
describe('templateUrl function', function() {
1261+
1262+
beforeEach(module(
1263+
function() {
1264+
directive('hello', valueFn({
1265+
restrict: 'CAM', templateUrl: function(e,t) {
1266+
return 'hello.html';
1267+
},
1268+
transclude: true
1269+
}));
1270+
directive('cau', valueFn({
1271+
restrict: 'CAM', templateUrl: function(e,t) {
1272+
expect(isElement(e)).toBeTruthy();
1273+
return 'cau'+t.test+'.html';
1274+
}
1275+
}));
1276+
}
1277+
));
1278+
1279+
it('should compile, link and flush the template inline when using functions as templateUrl', inject(
1280+
function($compile, $templateCache, $rootScope) {
1281+
$templateCache.put('hello.html', '<span>Hello, {{name}}!</span>');
1282+
$rootScope.name = 'Elvis';
1283+
element = $compile('<div><b hello></b></div>')($rootScope);
1284+
1285+
$rootScope.$digest();
1286+
1287+
expect(sortedHtml(element)).toBeOneOf(
1288+
'<div><b><span>Hello, Elvis!</span></b></div>',
1289+
'<div><b hello=""><span>Hello, Elvis!</span></b></div>' //ie8
1290+
);
1291+
}
1292+
));
1293+
1294+
it('should pass element and attributes to the templateUrl function', inject(
1295+
function($compile, $templateCache, $rootScope) {
1296+
$templateCache.put('cau2.html', '<span>Hey, {{name}}!</span>');
1297+
$templateCache.put('cau3.html', '<span>Say: Hey, {{name}}!</span>');
1298+
$rootScope.name = 'me';
1299+
element = $compile('<div><b cau test="2"></b><b cau test="3"></b></div>')($rootScope);
1300+
1301+
$rootScope.$digest();
1302+
1303+
expect(sortedHtml(element)).toBeOneOf(
1304+
'<div><b test="2"><span>Hey, me!</span></b><b test="3">' +
1305+
'<span>Say: Hey, me!</span></b></div>',
1306+
'<div><b cau="" test="2"><span>Hey, me!</span></b><b cau="" test="3">' +
1307+
'<span>Say: Hey, me!</span></b></div>' //ie8
1308+
);
1309+
}
1310+
));
1311+
});
1312+
12171313

12181314
describe('scope', function() {
12191315
var iscope;

0 commit comments

Comments
 (0)