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

feat(directives): $templateUrl #10

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions demo/web/book.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>Shadow backed template. Greeting from the controller:
<span ng-bind='greeting'></span>

<h2>Table of Contents</h2>
<ul class='nav nav-tabs'>
<li ng-repeat='chapter in chapters' ng-bind='chapter.title'></li>
</ul>
<content></content>
</div>
9 changes: 1 addition & 8 deletions demo/web/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,7 @@ class BookComponent {
BookController controller;
BookComponent(BookController this.controller);

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

attach(Scope scope) {
controller.attach(scope);
Expand Down
35 changes: 27 additions & 8 deletions lib/block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 = '<div>${directive.$template}</div>';
shadowBlock = $compiler(shadowRoot.nodes)(shadowRoot.nodes);
}

if (directive.$templateUrl != null) {
http.getString(directive.$templateUrl).then((data) {
shadowRoot.innerHtml = '<div>${data}</div>';
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);
}
}
}

Expand Down
8 changes: 0 additions & 8 deletions lib/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
2 changes: 2 additions & 0 deletions lib/directive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Directive {
int $priority = 0;
Type $controllerType;
String $template;
String $templateUrl;

bool isComponent = false;
bool isStructural = false;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ part of angular;

class Http {
async.Future<String> getString(String url, {bool withCredentials, void onProgress(dom.ProgressEvent e)}) =>
dom.HttpRequest.getString(url, withCredentials, onProgress);
dom.HttpRequest.getString(url, withCredentials: withCredentials, onProgress: onProgress);
}
8 changes: 7 additions & 1 deletion test/_http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ import 'package:angular/angular.dart';

class MockHttp extends Http {
Map<String, String> gets = {};
List futures = [];

expectGET(url, content) {
gets[url] = content;
}

flush() => Future.wait(futures);

Future<String> 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;
}
}

Expand Down
44 changes: 44 additions & 0 deletions test/templateurl_spec.dart
Original file line number Diff line number Diff line change
@@ -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', '<div log="SIMPLE">Simple!</div>');

var element = $('<div><simple-url log>ignore</replace><div>');
$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');
}));

}));
});
}