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

Commit 53b480f

Browse files
committed
feat(compiler): support component parameters.
1 parent a38a9bf commit 53b480f

File tree

4 files changed

+77
-14
lines changed

4 files changed

+77
-14
lines changed

lib/block.dart

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,7 @@ class Block implements ElementWrapper {
179179
try {
180180
var directiveInstance = injector.get(directiveType);
181181
if (directiveRef.directive.isComponent) {
182-
// TODO(misko): this way of getting shadowBlock is dumb!
183-
Block shadowBlock = directiveRef.blockTypes['']();
184-
directiveInstance = new ComponentWrapper(directiveInstance, node, shadowBlock);
182+
directiveInstance = new ComponentWrapper(directiveRef, directiveInstance, node, $injector.get(Parser));
185183
}
186184
directives.add(directiveInstance);
187185
} catch (e,s) {
@@ -337,20 +335,52 @@ class Block implements ElementWrapper {
337335
}
338336

339337
class ComponentWrapper {
338+
DirectiveRef directiveRef;
340339
dynamic controller;
341340
dom.Element elementRoot;
342341
Block shadowBlock;
343342
Scope shadowScope;
343+
Parser parser;
344344

345-
ComponentWrapper(this.controller, this.elementRoot, this.shadowBlock) {
345+
ComponentWrapper(this.directiveRef, this.controller, this.elementRoot, this.parser) {
346+
// TODO(misko): this way of getting shadowBlock is dumb!
347+
shadowBlock = directiveRef.blockTypes['']();
346348
var shadowRoot = elementRoot.createShadowRoot();
349+
// TODO(misko): this look should be moved into Block: shodowBlock.appendTo(shadowRoot);
347350
for (var i = 0, ii = shadowBlock.elements.length; i < ii; i++) {
348351
shadowRoot.append(shadowBlock.elements[i]);
349352
}
350353
}
351354

352355
attach(scope) {
353-
shadowScope = scope.$new();
356+
shadowScope = scope.$new(true);
357+
directiveRef.directive.$map.forEach((attrName, mapping) {
358+
var attrValue = elementRoot.attributes[attrName];
359+
if (mapping == '@') {
360+
shadowScope[attrName] = attrValue;
361+
} else if (mapping == '=') {
362+
ParsedFn expr = parser(attrValue);
363+
var shadowValue;
364+
shadowScope.$watch(
365+
() => expr(scope),
366+
(v) => shadowScope[attrName] = shadowValue = v);
367+
if (expr.assignable) {
368+
shadowScope.$watch(
369+
() => shadowScope[attrName],
370+
(v) {
371+
if (shadowValue != v) {
372+
shadowValue = v;
373+
expr.assign(scope, v);
374+
}
375+
} );
376+
}
377+
} else if (mapping == '&') {
378+
ParsedFn fn = parser(attrValue);
379+
shadowScope[attrName] = ([locals]) => fn(scope, locals);
380+
} else {
381+
throw "Unknown mapping $mapping for attribute $attrName.";
382+
}
383+
});
354384
controller.attach(shadowScope);
355385
shadowBlock.attach(shadowScope);
356386
}

lib/directive.dart

Lines changed: 5 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+
Map<String, String> $map;
1516

1617
bool isComponent = false;
1718
bool isStructural = false;
@@ -41,6 +42,7 @@ class Directive {
4142
$transclude = reflectStaticField(type, '\$transclude');
4243
$template = reflectStaticField(type, '\$template');
4344
$priority = reflectStaticField(type, '\$priority');
45+
$map = reflectStaticField(type, '\$map');
4446
if ($priority == null) {
4547
$priority = 0;
4648
}
@@ -49,6 +51,9 @@ class Directive {
4951
if ($selector != null) {
5052
$name = $selector;
5153
}
54+
if (isComponent && $map == null) {
55+
$map = new Map<String, String>();
56+
}
5257
}
5358
}
5459

lib/scope.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ class Scope implements Map {
104104
this[name] = value;
105105
return value;
106106
} else {
107-
super.noSuchMethod(invocation);
107+
if (this[name] is Function) {
108+
return this[name]();
109+
} else {
110+
super.noSuchMethod(invocation);
111+
}
108112
}
109113
}
110114

test/compiler_spec.dart

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ main() {
7070
template(element).attach($rootScope);
7171

7272
expect(element.text()).toEqual('');
73-
// TODO(deboer): Digest twice until we have dirty checking in the scope.
73+
// TODO(deboer): Digest twice until we have dirty checking in the scope.
7474
$rootScope.$digest();
7575
$rootScope.$digest();
7676
expect(element.text()).toEqual('Ab');
@@ -423,30 +423,54 @@ main() {
423423
describe('components', () {
424424
beforeEach(() {
425425
directives.register(SimpleComponent);
426+
directives.register(IoComponent);
426427
});
427428

428429
it('should create a simple component', inject((Compiler $compile) {
429430
$rootScope.name = 'OUTTER';
430-
var element = $(r'<div>{{name}}{{$id}}:<simple>{{name}}{{$id}}</simple></div>');
431+
$rootScope.sep = '-';
432+
var element = $(r'<div>{{name}}{{sep}}{{$id}}:<simple>{{name}}{{sep}}{{$id}}</simple></div>');
431433
BlockType blockType = $compile(element);
432434
Block block = blockType(element);
433435
block.attach($rootScope);
434436
$rootScope.$digest();
435437

436-
expect(element.textWithShadow()).toEqual('OUTTER_1:INNER_2(OUTTER_1)');
438+
expect(element.textWithShadow()).toEqual('OUTTER-_1:INNER_2(OUTTER-_1)');
439+
}));
440+
441+
it('should create a component with IO', inject((Compiler $compile) {
442+
var element = $(r'<div><io attr="A" expr="name" ondone="done=true"></io></div>');
443+
$compile(element)(element).attach($rootScope);
444+
$rootScope.name = 'misko';
445+
$rootScope.$apply();
446+
var component = $rootScope.ioComponent;
447+
expect(component.scope.name).toEqual(null);
448+
expect(component.scope.attr).toEqual('A');
449+
expect(component.scope.expr).toEqual('misko');
450+
component.scope.expr = 'angular';
451+
$rootScope.$apply();
452+
expect($rootScope.name).toEqual('angular');
453+
expect($rootScope.done).toEqual(null);
454+
component.scope.ondone();
455+
expect($rootScope.done).toEqual(true);
437456
}));
438457
});
439458
});
440459
}
441460

442461
class SimpleComponent {
443-
static String $template = r'{{name}}{{$id}}(<content>SHADOW-CONTENT</content>)';
444-
445-
SimpleComponent() {
446-
}
447-
462+
static String $template = r'{{name}}{{sep}}{{$id}}(<content>SHADOW-CONTENT</content>)';
448463
attach(Scope scope) {
449464
scope.name = 'INNER';
450465
}
466+
}
451467

468+
class IoComponent {
469+
static String $template = r'<content></content>';
470+
static Map $map = {"attr": "@", "expr": "=", "ondone": "&"};
471+
Scope scope;
472+
attach(Scope scope) {
473+
this.scope = scope;
474+
scope.$root.ioComponent = this;
475+
}
452476
}

0 commit comments

Comments
 (0)