Skip to content

Commit 0299d4a

Browse files
committed
fix(core): keep styles for ViewEncapsulation.Native isolated per component
BREAKING CHANGE: - `Renderer.registerComponent` now takes an additional argument. Fixes #4513 Closes #4524
1 parent a9aef8e commit 0299d4a

File tree

8 files changed

+50
-22
lines changed

8 files changed

+50
-22
lines changed

modules/angular2/src/core/linker/proto_view_factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class ProtoViewFactory {
7171
var compiledTemplateData = cmd.template.getData(this._appId);
7272

7373
this._renderer.registerComponentTemplate(cmd.templateId, compiledTemplateData.commands,
74-
compiledTemplateData.styles);
74+
compiledTemplateData.styles, cmd.nativeShadow);
7575
var boundPipes = this._flattenPipes(view).map(pipe => this._bindPipe(pipe));
7676

7777
nestedProtoView = new AppProtoView(compiledTemplateData.commands, ViewType.COMPONENT, true,

modules/angular2/src/core/render/api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ export class Renderer {
230230
* Once a template is registered it can be referenced via {@link RenderBeginComponentCmd} when
231231
* {@link #createProtoView creating Render ProtoView}.
232232
*/
233-
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[]) {}
233+
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
234+
nativeShadow: boolean) {}
234235

235236
/**
236237
* Creates a {@link RenderProtoViewRef} from an array of {@link RenderTemplateCmd}`s.

modules/angular2/src/core/render/dom/dom_renderer.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {camelCaseToDashCase} from './util';
3535
@Injectable()
3636
export class DomRenderer implements Renderer, NodeFactory<Node> {
3737
private _componentCmds: Map<number, RenderTemplateCmd[]> = new Map<number, RenderTemplateCmd[]>();
38+
private _nativeShadowStyles: Map<number, string[]> = new Map<number, string[]>();
3839
private _document;
3940

4041
/**
@@ -46,9 +47,14 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
4647
this._document = document;
4748
}
4849

49-
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[]) {
50+
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
51+
nativeShadow: boolean) {
5052
this._componentCmds.set(templateId, commands);
51-
this._domSharedStylesHost.addStyles(styles);
53+
if (nativeShadow) {
54+
this._nativeShadowStyles.set(templateId, styles);
55+
} else {
56+
this._domSharedStylesHost.addStyles(styles);
57+
}
5258
}
5359

5460
resolveComponentTemplate(templateId: number): RenderTemplateCmd[] {
@@ -193,7 +199,14 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
193199
DOM.setAttribute(node, attrNameAndValues[attrIdx], attrNameAndValues[attrIdx + 1]);
194200
}
195201
}
196-
createShadowRoot(host: Node): Node { return DOM.createShadowRoot(host); }
202+
createShadowRoot(host: Node, templateId: number): Node {
203+
var sr = DOM.createShadowRoot(host);
204+
var styles = this._nativeShadowStyles.get(templateId);
205+
for (var i = 0; i < styles.length; i++) {
206+
DOM.appendChild(sr, DOM.createStyleElement(styles[i]));
207+
}
208+
return sr;
209+
}
197210
createText(value: string): Node { return DOM.createTextNode(isPresent(value) ? value : ''); }
198211
appendChild(parent: Node, child: Node) { DOM.appendChild(parent, child); }
199212
on(element: Node, eventName: string, callback: Function) {

modules/angular2/src/core/render/view_factory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export interface NodeFactory<N> {
7070
createTemplateAnchor(attrNameAndValues: string[]): N;
7171
createElement(name: string, attrNameAndValues: string[]): N;
7272
mergeElement(existing: N, attrNameAndValues: string[]);
73-
createShadowRoot(host: N): N;
73+
createShadowRoot(host: N, templateId: number): N;
7474
createText(value: string): N;
7575
appendChild(parent: N, child: N);
7676
on(element: N, eventName: string, callback: Function);
@@ -125,7 +125,7 @@ class RenderViewBuilder<N> implements RenderCommandVisitor {
125125
var el = this._beginElement(cmd);
126126
var root = el;
127127
if (cmd.nativeShadow) {
128-
root = this.factory.createShadowRoot(el);
128+
root = this.factory.createShadowRoot(el, cmd.templateId);
129129
this.nativeShadowRoots.push(root);
130130
}
131131
var component = new Component(el, root, cmd, this.factory, this.allBuilders);

modules/angular2/src/web_workers/ui/renderer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export class MessageBasedRenderer {
3131
var broker = this._brokerFactory.createMessageBroker(RENDERER_CHANNEL);
3232
this._bus.initChannel(EVENT_CHANNEL);
3333

34-
broker.registerMethod("registerComponentTemplate", [PRIMITIVE, WebWorkerTemplateCmd, PRIMITIVE],
34+
broker.registerMethod("registerComponentTemplate",
35+
[PRIMITIVE, WebWorkerTemplateCmd, PRIMITIVE, PRIMITIVE],
3536
bind(this._renderer.registerComponentTemplate, this._renderer));
3637
broker.registerMethod("createProtoView", [WebWorkerTemplateCmd, PRIMITIVE],
3738
bind(this._createProtoView, this));

modules/angular2/src/web_workers/worker/renderer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ export class WebWorkerRenderer implements Renderer {
3535
this._messageBroker = messageBrokerFactory.createMessageBroker(RENDERER_CHANNEL);
3636
}
3737

38-
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[]) {
38+
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
39+
nativeShadow: boolean) {
3940
var fnArgs = [
4041
new FnArg(templateId, null),
4142
new FnArg(commands, WebWorkerTemplateCmd),
42-
new FnArg(styles, null)
43+
new FnArg(styles, null),
44+
new FnArg(nativeShadow, null)
4345
];
4446
var args = new UiArguments("registerComponentTemplate", fnArgs);
4547
this._messageBroker.runOnService(args, null);

modules/angular2/test/core/linker/projection_integration_spec.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,18 @@ export function main() {
423423
}));
424424

425425
if (DOM.supportsNativeShadowDOM()) {
426-
it('should support native content projection',
426+
it('should support native content projection and isolate styles per component',
427427
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
428428
tcb.overrideView(MainComp, new ViewMetadata({
429-
template: '<simple-native>' +
430-
'<div>A</div>' +
431-
'</simple-native>',
432-
directives: [SimpleNative]
429+
template: '<simple-native1><div>A</div></simple-native1>' +
430+
'<simple-native2><div>B</div></simple-native2>',
431+
directives: [SimpleNative1, SimpleNative2]
433432
}))
434433
.createAsync(MainComp)
435434
.then((main) => {
436-
437-
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
435+
var childNodes = DOM.childNodes(main.debugElement.nativeElement);
436+
expect(childNodes[0]).toHaveText('div {color: red}SIMPLE1(A)');
437+
expect(childNodes[1]).toHaveText('div {color: blue}SIMPLE2(B)');
438438
async.done();
439439
});
440440
}));
@@ -485,13 +485,24 @@ class Simple {
485485
stringProp: string = '';
486486
}
487487

488-
@Component({selector: 'simple-native'})
488+
@Component({selector: 'simple-native1'})
489+
@View({
490+
template: 'SIMPLE1(<content></content>)',
491+
directives: [],
492+
encapsulation: ViewEncapsulation.Native,
493+
styles: ['div {color: red}']
494+
})
495+
class SimpleNative1 {
496+
}
497+
498+
@Component({selector: 'simple-native2'})
489499
@View({
490-
template: 'SIMPLE(<content></content>)',
500+
template: 'SIMPLE2(<content></content>)',
491501
directives: [],
492-
encapsulation: ViewEncapsulation.Native
502+
encapsulation: ViewEncapsulation.Native,
503+
styles: ['div {color: blue}']
493504
})
494-
class SimpleNative {
505+
class SimpleNative2 {
495506
}
496507

497508
@Component({selector: 'empty'})

modules/angular2/test/core/render/view_factory_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ class DomNodeFactory implements NodeFactory<Node> {
521521
DOM.setAttribute(el, attrNameAndValues[attrIdx], attrNameAndValues[attrIdx + 1]);
522522
}
523523
}
524-
createShadowRoot(host: Node): Node {
524+
createShadowRoot(host: Node, templateId: number): Node {
525525
var root = DOM.createElement('shadow-root');
526526
DOM.appendChild(host, root);
527527
return root;

0 commit comments

Comments
 (0)