diff --git a/demo/web/book.html b/demo/web/book.html
new file mode 100644
index 000000000..51f1a95d0
--- /dev/null
+++ b/demo/web/book.html
@@ -0,0 +1,9 @@
+
Shadow backed template. Greeting from the controller:
+
+
+
Table of Contents
+
+
+
diff --git a/demo/web/main.dart b/demo/web/main.dart
index 0e105b579..82b5b1fbd 100644
--- a/demo/web/main.dart
+++ b/demo/web/main.dart
@@ -60,14 +60,7 @@ class BookComponent {
BookController controller;
BookComponent(BookController this.controller);
- static String $template = '''
- Shadow backed template. Greeting from the controller:
-
-
Table of Contents
-
-
''';
+ static String $templateUrl = 'book.html';
attach(Scope scope) {
controller.attach(scope);
diff --git a/lib/block.dart b/lib/block.dart
index 609ad2112..916af2da0 100644
--- a/lib/block.dart
+++ b/lib/block.dart
@@ -179,9 +179,8 @@ class Block implements ElementWrapper {
try {
var directiveInstance = injector.get(directiveType);
if (directiveRef.directive.isComponent) {
- // TODO(misko): this way of getting shadowBlock is dumb!
- Block shadowBlock = directiveRef.blockTypes['']();
- directiveInstance = new ComponentWrapper(directiveInstance, node, shadowBlock);
+ directiveInstance = new ComponentWrapper(directiveInstance, node, $injector.get(Compiler),
+ directiveRef, $injector.get(Http));
}
directives.add(directiveInstance);
} catch (e,s) {
@@ -339,20 +338,40 @@ class Block implements ElementWrapper {
class ComponentWrapper {
dynamic controller;
dom.Element elementRoot;
- Block shadowBlock;
Scope shadowScope;
+ Block shadowBlock;
- ComponentWrapper(this.controller, this.elementRoot, this.shadowBlock) {
+ ComponentWrapper(this.controller, this.elementRoot, Compiler $compiler, DirectiveRef directiveRef, Http http) {
+ var directive = directiveRef.directive;
var shadowRoot = elementRoot.createShadowRoot();
- for (var i = 0, ii = shadowBlock.elements.length; i < ii; i++) {
- shadowRoot.append(shadowBlock.elements[i]);
+
+ // There is support here for directives having both $template and
+ // $templateUrl. This could be a clever way to add a 'LOADING'
+ // message.
+ if (directive.$template != null) {
+ shadowRoot.innerHtml = '${directive.$template}
';
+ shadowBlock = $compiler(shadowRoot.nodes)(shadowRoot.nodes);
+ }
+
+ if (directive.$templateUrl != null) {
+ http.getString(directive.$templateUrl).then((data) {
+ shadowRoot.innerHtml = '${data}
';
+ shadowBlock = $compiler(shadowRoot.nodes)(shadowRoot.nodes);
+ // re-attach the scope.
+ if (shadowScope != null) {
+ shadowBlock.attach(shadowScope);
+ shadowScope.$digest();
+ }
+ });
}
}
attach(scope) {
shadowScope = scope.$new();
controller.attach(shadowScope);
- shadowBlock.attach(shadowScope);
+ if (shadowBlock != null) {
+ shadowBlock.attach(shadowScope);
+ }
}
}
diff --git a/lib/compiler.dart b/lib/compiler.dart
index bf7fb23e4..99e89e7ef 100644
--- a/lib/compiler.dart
+++ b/lib/compiler.dart
@@ -65,14 +65,6 @@ class Compiler {
}
directiveRef.blockTypes = blockTypes;
usableDirectiveRefs.add(directiveRef);
- if (directive.$template != null) {
- // TODO(deboer): port this function.
- denormalizeTemplate(x) => x;
- var templateValue = denormalizeTemplate(directive.$template);
- var div = new dom.DivElement();
- div.innerHtml = templateValue;
- directiveRef.blockTypes = {'': this(div.nodes)};
- }
}
if (compileChildren && domCursor.descend()) {
diff --git a/lib/directive.dart b/lib/directive.dart
index 192c5ac65..798ef8c61 100644
--- a/lib/directive.dart
+++ b/lib/directive.dart
@@ -12,6 +12,7 @@ class Directive {
int $priority = 0;
Type $controllerType;
String $template;
+ String $templateUrl;
bool isComponent = false;
bool isStructural = false;
@@ -40,6 +41,7 @@ class Directive {
// It would be awesome if $transclude could be an enum.
$transclude = reflectStaticField(type, '\$transclude');
$template = reflectStaticField(type, '\$template');
+ $templateUrl = reflectStaticField(type, '\$templateUrl');
$priority = reflectStaticField(type, '\$priority');
if ($priority == null) {
$priority = 0;
diff --git a/lib/http.dart b/lib/http.dart
index 85461cd02..07569912c 100644
--- a/lib/http.dart
+++ b/lib/http.dart
@@ -2,5 +2,5 @@ part of angular;
class Http {
async.Future getString(String url, {bool withCredentials, void onProgress(dom.ProgressEvent e)}) =>
- dom.HttpRequest.getString(url, withCredentials, onProgress);
+ dom.HttpRequest.getString(url, withCredentials: withCredentials, onProgress: onProgress);
}
diff --git a/test/_http.dart b/test/_http.dart
index 091558c85..e18c72535 100644
--- a/test/_http.dart
+++ b/test/_http.dart
@@ -7,13 +7,19 @@ import 'package:angular/angular.dart';
class MockHttp extends Http {
Map gets = {};
+ List futures = [];
+
expectGET(url, content) {
gets[url] = content;
}
+ flush() => Future.wait(futures);
+
Future getString(String url, {bool withCredentials, void onProgress(ProgressEvent e)}) {
if (!gets.containsKey(url)) throw "Unexpected URL $url";
- return new Future.value(gets.remove(url));
+ var f = new Future.value(gets.remove(url));
+ futures.add(f);
+ return f;
}
}
diff --git a/test/templateurl_spec.dart b/test/templateurl_spec.dart
new file mode 100644
index 000000000..74755186c
--- /dev/null
+++ b/test/templateurl_spec.dart
@@ -0,0 +1,44 @@
+import "_specs.dart";
+import "_log.dart";
+import "_http.dart";
+
+class LogAttrDirective {
+ static var $priority = 0;
+ Log log;
+ LogAttrDirective(Log this.log, DirectiveValue value) {
+ log(value.value == "" ? "LOG" : value.value);
+ }
+ attach(Scope scope) {}
+}
+
+class SimpleUrlComponent {
+ static String $templateUrl = 'simple.html';
+ attach(Scope scope) {}
+}
+
+main() {
+ describe('templateUrl', () {
+ beforeEach(module((module) {
+ var mockHttp = new MockHttp();
+ module.value(MockHttp, mockHttp);
+ module.value(Http, mockHttp);
+ module.directive(LogAttrDirective);
+ module.directive(SimpleUrlComponent);
+ }));
+
+ it('should replace element with template from url', inject((MockHttp $http, Compiler $compile, Scope $rootScope, Log log) {
+ $http.expectGET('simple.html', 'Simple!
');
+
+ var element = $('ignore');
+ $compile(element)(element)..attach($rootScope);
+
+ $http.flush().then(expectAsync1((data) {
+ expect(renderedText(element)).toEqual('Simple!');
+ // Note: There is no ordering. It is who ever comes off the wire first!
+ expect(log.result()).toEqual('LOG; SIMPLE');
+ }));
+
+ }));
+ });
+}
+