Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 11babbd

Browse files
committed
feat(directives): $templateUrl
1 parent 53b480f commit 11babbd

File tree

8 files changed

+95
-27
lines changed

8 files changed

+95
-27
lines changed

demo/web/book.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<div>Shadow backed template. Greeting from the controller:
2+
<span ng-bind='greeting'></span>
3+
4+
<h2>Table of Contents</h2>
5+
<ul class='nav nav-tabs'>
6+
<li ng-repeat='chapter in chapters' ng-bind='chapter.title'></li>
7+
</ul>
8+
<content></content>
9+
</div>

demo/web/main.dart

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,7 @@ class BookComponent {
6060
BookController controller;
6161
BookComponent(BookController this.controller);
6262

63-
static String $template = '''
64-
<div>Shadow backed template. Greeting from the controller:
65-
<span ng-bind='greeting'></span>
66-
<h2>Table of Contents</h2><ul class='nav nav-tabs'>
67-
<li ng-repeat='chapter in chapters' ng-bind='chapter.title'></li>
68-
</ul>
69-
<content></content>
70-
</div>''';
63+
static String $templateUrl = 'book.html';
7164

7265
attach(Scope scope) {
7366
controller.attach(scope);

lib/block.dart

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ class Block implements ElementWrapper {
179179
try {
180180
var directiveInstance = injector.get(directiveType);
181181
if (directiveRef.directive.isComponent) {
182-
directiveInstance = new ComponentWrapper(directiveRef, directiveInstance, node, $injector.get(Parser));
182+
directiveInstance = new ComponentWrapper(directiveRef, directiveInstance, node,
183+
$injector.get(Parser), $injector.get(Compiler), $injector.get(Http));
184+
183185
}
184186
directives.add(directiveInstance);
185187
} catch (e,s) {
@@ -338,17 +340,35 @@ class ComponentWrapper {
338340
DirectiveRef directiveRef;
339341
dynamic controller;
340342
dom.Element elementRoot;
341-
Block shadowBlock;
342343
Scope shadowScope;
343344
Parser parser;
345+
Block shadowBlock;
344346

345-
ComponentWrapper(this.directiveRef, this.controller, this.elementRoot, this.parser) {
346-
// TODO(misko): this way of getting shadowBlock is dumb!
347-
shadowBlock = directiveRef.blockTypes['']();
347+
348+
ComponentWrapper(this.directiveRef, this.controller, this.elementRoot, this.parser, $compiler, $http) {
349+
var directive = directiveRef.directive;
348350
var shadowRoot = elementRoot.createShadowRoot();
349-
// TODO(misko): this look should be moved into Block: shodowBlock.appendTo(shadowRoot);
350-
for (var i = 0, ii = shadowBlock.elements.length; i < ii; i++) {
351-
shadowRoot.append(shadowBlock.elements[i]);
351+
352+
_appendAndCompileTemplate(data) {
353+
shadowRoot.innerHtml = data;
354+
shadowBlock = $compiler(shadowRoot.nodes)(shadowRoot.nodes);
355+
}
356+
// There is support here for directives having both $template and
357+
// $templateUrl. This could be a clever way to add a 'LOADING'
358+
// message.
359+
if (directive.$template != null) {
360+
_appendAndCompileTemplate(directive.$template);
361+
}
362+
363+
if (directive.$templateUrl != null) {
364+
$http.getString(directive.$templateUrl).then((data) {
365+
_appendAndCompileTemplate(data);
366+
// re-attach the scope.
367+
if (shadowScope != null) {
368+
shadowBlock.attach(shadowScope);
369+
shadowScope.$digest();
370+
}
371+
});
352372
}
353373
}
354374

@@ -382,7 +402,9 @@ class ComponentWrapper {
382402
}
383403
});
384404
controller.attach(shadowScope);
385-
shadowBlock.attach(shadowScope);
405+
if (shadowBlock != null) {
406+
shadowBlock.attach(shadowScope);
407+
}
386408
}
387409
}
388410

lib/compiler.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,6 @@ class Compiler {
6565
}
6666
directiveRef.blockTypes = blockTypes;
6767
usableDirectiveRefs.add(directiveRef);
68-
if (directive.$template != null) {
69-
// TODO(deboer): port this function.
70-
denormalizeTemplate(x) => x;
71-
var templateValue = denormalizeTemplate(directive.$template);
72-
var div = new dom.DivElement();
73-
div.innerHtml = templateValue;
74-
directiveRef.blockTypes = {'': this(div.nodes)};
75-
}
7668
}
7769

7870
if (compileChildren && domCursor.descend()) {

lib/directive.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Directive {
1212
int $priority = 0;
1313
Type $controllerType;
1414
String $template;
15+
String $templateUrl;
1516
Map<String, String> $map;
1617

1718
bool isComponent = false;
@@ -41,6 +42,7 @@ class Directive {
4142
// It would be awesome if $transclude could be an enum.
4243
$transclude = reflectStaticField(type, '\$transclude');
4344
$template = reflectStaticField(type, '\$template');
45+
$templateUrl = reflectStaticField(type, '\$templateUrl');
4446
$priority = reflectStaticField(type, '\$priority');
4547
$map = reflectStaticField(type, '\$map');
4648
if ($priority == null) {

lib/http.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ part of angular;
22

33
class Http {
44
async.Future<String> getString(String url, {bool withCredentials, void onProgress(dom.ProgressEvent e)}) =>
5-
dom.HttpRequest.getString(url, withCredentials, onProgress);
5+
dom.HttpRequest.getString(url, withCredentials: withCredentials, onProgress: onProgress);
66
}

test/_http.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@ import 'package:angular/angular.dart';
77

88
class MockHttp extends Http {
99
Map<String, String> gets = {};
10+
List futures = [];
11+
1012
expectGET(url, content) {
1113
gets[url] = content;
1214
}
1315

16+
flush() => Future.wait(futures);
17+
1418
Future<String> getString(String url, {bool withCredentials, void onProgress(ProgressEvent e)}) {
1519
if (!gets.containsKey(url)) throw "Unexpected URL $url";
16-
return new Future.value(gets.remove(url));
20+
var f = new Future.value(gets.remove(url));
21+
futures.add(f);
22+
return f;
1723
}
1824
}
1925

test/templateurl_spec.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import "_specs.dart";
2+
import "_log.dart";
3+
import "_http.dart";
4+
5+
class LogAttrDirective {
6+
static var $priority = 0;
7+
Log log;
8+
LogAttrDirective(Log this.log, DirectiveValue value) {
9+
log(value.value == "" ? "LOG" : value.value);
10+
}
11+
attach(Scope scope) {}
12+
}
13+
14+
class SimpleUrlComponent {
15+
static String $templateUrl = 'simple.html';
16+
attach(Scope scope) {}
17+
}
18+
19+
main() {
20+
describe('templateUrl', () {
21+
beforeEach(module((module) {
22+
var mockHttp = new MockHttp();
23+
module.value(MockHttp, mockHttp);
24+
module.value(Http, mockHttp);
25+
module.directive(LogAttrDirective);
26+
module.directive(SimpleUrlComponent);
27+
}));
28+
29+
it('should replace element with template from url', inject((MockHttp $http, Compiler $compile, Scope $rootScope, Log log) {
30+
$http.expectGET('simple.html', '<div log="SIMPLE">Simple!</div>');
31+
32+
var element = $('<div><simple-url log>ignore</replace><div>');
33+
$compile(element)(element)..attach($rootScope);
34+
35+
$http.flush().then(expectAsync1((data) {
36+
expect(renderedText(element)).toEqual('Simple!');
37+
// Note: There is no ordering. It is who ever comes off the wire first!
38+
expect(log.result()).toEqual('LOG; SIMPLE');
39+
}));
40+
41+
}));
42+
});
43+
}
44+

0 commit comments

Comments
 (0)