Skip to content

Commit 5cd1ae9

Browse files
Merge pull request #191 from bouncehead13/dev
Allow Scoped Styles to Work With Child Components
2 parents a95d9e1 + b76f109 commit 5cd1ae9

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

packages/sitecore-jss-angular/src/components/placeholder.component.spec.ts

+30
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class TestDownloadCalloutComponent {
3434

3535
@Component({
3636
selector: 'test-home',
37+
styles: [ 'sc-placeholder[name="page-content"] { background-color: red }' ],
3738
template: `
3839
<sc-placeholder name="page-header" [rendering]="rendering"></sc-placeholder>
3940
<sc-placeholder name="page-content" [rendering]="rendering"></sc-placeholder>
@@ -167,6 +168,35 @@ describe('<sc-placeholder />', () => {
167168
});
168169
}));
169170

171+
it('should copy parent style attribute', async(() => {
172+
const component = nonEeDevData.sitecore.route;
173+
const phKey = 'main';
174+
comp.name = phKey;
175+
comp.rendering = component;
176+
fixture.detectChanges();
177+
178+
fixture.whenStable()
179+
.then(() => {
180+
fixture.detectChanges();
181+
182+
// let's grab the style name from the parent
183+
let parentKey = '';
184+
const homeComp = de.query(By.directive(TestHomeComponent));
185+
const homeAttributes = homeComp.nativeElement.attributes;
186+
if (homeAttributes.length) {
187+
const parentAttribute = homeComp.nativeElement.attributes.item(0).name;
188+
parentKey = parentAttribute.replace('_nghost-', '');
189+
}
190+
191+
fixture.whenStable()
192+
.then(() => {
193+
fixture.detectChanges();
194+
const downloadCallout = de.query(By.directive(TestDownloadCalloutComponent));
195+
expect(downloadCallout.nativeElement.attributes.item(0).name).toEqual(`_ngcontent-${parentKey}`);
196+
});
197+
});
198+
}));
199+
170200
it('should skip rendering unknown components', async(() => {
171201
const phKey = 'main';
172202
const route = {

packages/sitecore-jss-angular/src/components/placeholder.component.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ import {
44
ComponentFactoryResolver,
55
ContentChild,
66
DoCheck,
7+
ElementRef,
78
EventEmitter,
89
Inject,
910
Input,
1011
KeyValueDiffer,
1112
KeyValueDiffers,
1213
OnChanges,
1314
OnDestroy,
15+
OnInit,
1416
Output,
17+
Renderer2,
1518
SimpleChanges,
1619
Type,
1720
ViewChild,
@@ -43,11 +46,12 @@ function getPlaceholder(rendering: ComponentRendering, name: string) {
4346
<ng-template #view></ng-template>
4447
`,
4548
})
46-
export class PlaceholderComponent implements OnChanges, DoCheck, OnDestroy {
49+
export class PlaceholderComponent implements OnInit, OnChanges, DoCheck, OnDestroy {
4750
private _inputs: { [key: string]: any };
4851
private _differ: KeyValueDiffer<string, any>;
4952
private _componentInstances: any[] = [];
5053
private destroyed = false;
54+
private parentStyleAttribute: string = '';
5155
public isLoading = true;
5256

5357
@Input() name?: string;
@@ -76,9 +80,26 @@ export class PlaceholderComponent implements OnChanges, DoCheck, OnDestroy {
7680
private differs: KeyValueDiffers,
7781
private componentFactory: JssComponentFactoryService,
7882
private changeDetectorRef: ChangeDetectorRef,
83+
private elementRef: ElementRef,
84+
private renderer: Renderer2,
7985
@Inject(PLACEHOLDER_MISSING_COMPONENT_COMPONENT) private missingComponentComponent: Type<any>
8086
) { }
8187

88+
ngOnInit() {
89+
// just to ensure the element exists
90+
const elem = this.elementRef.nativeElement;
91+
92+
if (elem) {
93+
const attributes: NamedNodeMap = elem.attributes;
94+
for (let i = 0; i < attributes.length; i++) {
95+
const attr: Attr | null = attributes.item(i);
96+
if (attr && attr.name.indexOf('_ngcontent') !== -1) {
97+
this.parentStyleAttribute = attr.name;
98+
}
99+
}
100+
}
101+
}
102+
82103
ngOnDestroy() {
83104
this.destroyed = true;
84105
this._componentInstances = [];
@@ -199,7 +220,14 @@ export class PlaceholderComponent implements OnChanges, DoCheck, OnDestroy {
199220
const componentFactory =
200221
rendering.componentFactory || this.componentFactoryResolver.resolveComponentFactory(rendering.componentImplementation);
201222

202-
const componentInstance = this.view.createComponent(componentFactory, index).instance;
223+
// apply the parent style attribute _ngcontent
224+
// work-around for https://github.com/angular/angular/issues/12215
225+
const createdComponentRef = this.view.createComponent(componentFactory, index);
226+
if (this.parentStyleAttribute) {
227+
this.renderer.setAttribute(createdComponentRef.location.nativeElement, this.parentStyleAttribute, '');
228+
}
229+
230+
const componentInstance = createdComponentRef.instance;
203231
componentInstance.rendering = rendering.componentDefinition;
204232
if (this._inputs) {
205233
this._setComponentInputs(componentInstance, this._inputs);

0 commit comments

Comments
 (0)