Skip to content

Commit d520da5

Browse files
committed
Merge pull request #126 from NativeScript/hdeshev/styles-fix
Fix multiple component styles
2 parents 659182c + 44d0430 commit d520da5

File tree

4 files changed

+69
-17
lines changed

4 files changed

+69
-17
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nativescript-angular",
3-
"version": "0.0.36",
3+
"version": "0.0.37",
44
"description": "",
55
"homepage": "http://www.telerik.com",
66
"bugs": "http://www.telerik.com",

src/nativescript-angular/renderer.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {View} from "ui/core/view";
1313
import {topmost} from 'ui/frame';
1414
import {Page} from 'ui/page';
1515
import * as util from "./view-util";
16+
import {escapeRegexSymbols} from "utils/utils";
1617

1718
export { rendererTraceCategory } from "./view-util";
1819

@@ -60,11 +61,20 @@ export class NativeScriptRenderer extends Renderer {
6061
for(let i = 0; i < stylesLength; i++) {
6162
this.hasComponentStyles = true;
6263
let cssString = componentProto.styles[i] + "";
63-
page.addCss(cssString.replace(COMPONENT_VARIABLE, componentProto.id));
64+
const realCSS = this.replaceNgAttribute(cssString, this.componentProtoId);
65+
page.addCss(realCSS);
6466
}
6567
util.traceLog('NativeScriptRenderer created');
6668
}
6769

70+
private attrReplacer = new RegExp(escapeRegexSymbols(CONTENT_ATTR), "g");
71+
private attrSanitizer = /-/g;
72+
73+
private replaceNgAttribute(input: string, componentId: string): string {
74+
return input.replace(this.attrReplacer,
75+
"_ng_content_" + componentId.replace(this.attrSanitizer, "_"));
76+
}
77+
6878
renderComponent(componentProto: RenderComponentType): Renderer {
6979
return this._rootRenderer.renderComponent(componentProto);
7080
}
@@ -175,13 +185,14 @@ export class NativeScriptRenderer extends Renderer {
175185

176186
public createElement(parentElement: util.NgView, name: string): util.NgView {
177187
util.traceLog('NativeScriptRenderer.createElement: ' + name + ' parent: ' + parentElement + ', ' + (parentElement ? parentElement.nodeName : 'null'));
178-
let result = util.createView(name, parentElement);
179-
// adding an attribute (property) to {N} view for applying component specific css.
180-
// The property value is generated by angular2 infrastructure on conponent creation.
181-
if (this.hasComponentStyles) {
182-
result[CONTENT_ATTR.replace(COMPONENT_VARIABLE, this.componentProtoId)] = true;
183-
}
184-
return result;
188+
return util.createView(name, parentElement, (view) => {
189+
// Set an attribute to the view to scope component-specific css.
190+
// The property name is pre-generated by Angular.
191+
if (this.hasComponentStyles) {
192+
const cssAttribute = this.replaceNgAttribute(CONTENT_ATTR, this.componentProtoId);
193+
view[cssAttribute] = true;
194+
}
195+
});
185196
}
186197

187198
public createText(value: string): util.NgView {

src/nativescript-angular/view-util.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,27 @@ export function getChildIndex(parent: any, child: NgView) {
8484
}
8585
}
8686

87-
function createAndAttach(name: string, viewClass: ViewClass, parent: NgView): NgView {
87+
function createAndAttach(name: string, viewClass: ViewClass, parent: NgView, beforeAttach?: BeforeAttachAction): NgView {
8888
const view = <NgView>new viewClass();
8989
view.nodeName = name;
9090
view.meta = getViewMeta(name);
91+
if (beforeAttach) {
92+
beforeAttach(view);
93+
}
9194
if (parent) {
9295
insertChild(parent, view);
9396
}
9497
return view;
9598
}
9699

97-
export function createView(name: string, parent: NgView): NgView {
100+
export type BeforeAttachAction = (view: View) => void;
101+
102+
export function createView(name: string, parent: NgView, beforeAttach?: BeforeAttachAction): NgView {
98103
if (isKnownView(name)) {
99104
const viewClass = getViewClass(name);
100-
return createAndAttach(name, viewClass, parent);
105+
return createAndAttach(name, viewClass, parent, beforeAttach);
101106
} else {
102-
return createViewContainer(name, parent);
107+
return createViewContainer(name, parent, beforeAttach);
103108
}
104109
}
105110

@@ -111,11 +116,11 @@ export function createText(value: string): NgView {
111116
return text;
112117
}
113118

114-
export function createViewContainer(name: string, parentElement: NgView) {
119+
export function createViewContainer(name: string, parentElement: NgView, beforeAttach: BeforeAttachAction) {
115120
//HACK: Using a ContentView here, so that it creates a native View object
116121
traceLog('Creating view container in:' + parentElement);
117122

118-
const layout = createView('ProxyViewContainer', parentElement);
123+
const layout = createView('ProxyViewContainer', parentElement, beforeAttach);
119124
layout.nodeName = 'ProxyViewContainer';
120125
return layout;
121126
}

tests/app/tests/renderer-tests.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {ProxyViewContainer} from "ui/proxy-view-container";
88
import {Red} from "color/known-colors";
99
import {dumpView} from "./test-utils";
1010
import {TestApp} from "./test-app";
11+
import {LayoutBase} from "ui/layouts/layout-base"
1112

1213
@Component({
1314
template: `<StackLayout><Label text="Layout"></Label></StackLayout>`
@@ -63,6 +64,27 @@ export class StyledLabelCmp {
6364
}
6465
}
6566

67+
@Component({
68+
selector: "styled-label-cmp2",
69+
styles: [
70+
`Label { color: red; }`,
71+
`
72+
StackLayout { color: brick; }
73+
TextField { color: red; background-color: lime; }
74+
`,
75+
],
76+
template: `
77+
<StackLayout orientation="horizontal">
78+
<Label text="Styled!"></Label>
79+
<TextField text="Styled too!"></TextField>
80+
</StackLayout>
81+
`
82+
})
83+
export class StyledLabelCmp2 {
84+
constructor(public elementRef: ElementRef) {
85+
}
86+
}
87+
6688
@Component({
6789
selector: "ng-if-label",
6890
template: `<Label *ngIf="show" text="iffed"></Label>`
@@ -122,14 +144,28 @@ describe('Renderer E2E', () => {
122144
});
123145
});
124146

125-
it("applies component styles", () => {
147+
it("applies component styles from single source", () => {
126148
return testApp.loadComponent(StyledLabelCmp).then((componentRef) => {
127149
const componentRoot = componentRef.instance.elementRef.nativeElement;
128150
const label = (<ProxyViewContainer>componentRoot).getChildAt(0);
129151
assert.equal(Red, label.style.color.hex);
130152
});
131153
});
132154

155+
it("applies component styles from multiple sources", () => {
156+
return testApp.loadComponent(StyledLabelCmp2).then((componentRef) => {
157+
const componentRoot = componentRef.instance.elementRef.nativeElement;
158+
const layout = (<ProxyViewContainer>componentRoot).getChildAt(0);
159+
160+
const label = (<LayoutBase>layout).getChildAt(0);
161+
assert.equal(Red, label.style.color.hex);
162+
163+
const textField = (<LayoutBase>layout).getChildAt(1);
164+
console.log("TEXT style.color: " + textField.style.color);
165+
assert.equal(Red, textField.style.color.hex);
166+
});
167+
});
168+
133169
describe("Structural directives", () => {
134170
it("ngIf hides component when false", () => {
135171
return testApp.loadComponent(NgIfLabel).then((componentRef) => {
@@ -180,4 +216,4 @@ describe('Renderer E2E', () => {
180216
});
181217
});
182218
})
183-
})
219+
})

0 commit comments

Comments
 (0)