From 746b435c697cd829000c912e955a935771f92b8d Mon Sep 17 00:00:00 2001 From: Hristo Deshev Date: Mon, 21 Mar 2016 17:16:44 +0200 Subject: [PATCH 1/2] Fix multiple style resolutions per component. --- src/nativescript-angular/renderer.ts | 27 ++++++++++++------ src/nativescript-angular/view-util.ts | 17 ++++++++---- tests/app/tests/renderer-tests.ts | 40 +++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/nativescript-angular/renderer.ts b/src/nativescript-angular/renderer.ts index 7d07d9866..f93e3d3c5 100644 --- a/src/nativescript-angular/renderer.ts +++ b/src/nativescript-angular/renderer.ts @@ -13,6 +13,7 @@ import {View} from "ui/core/view"; import {topmost} from 'ui/frame'; import {Page} from 'ui/page'; import * as util from "./view-util"; +import {escapeRegexSymbols} from "utils/utils"; export { rendererTraceCategory } from "./view-util"; @@ -60,11 +61,20 @@ export class NativeScriptRenderer extends Renderer { for(let i = 0; i < stylesLength; i++) { this.hasComponentStyles = true; let cssString = componentProto.styles[i] + ""; - page.addCss(cssString.replace(COMPONENT_VARIABLE, componentProto.id)); + const realCSS = this.replaceNgAttribute(cssString, this.componentProtoId); + page.addCss(realCSS); } util.traceLog('NativeScriptRenderer created'); } + private attrReplacer = new RegExp(escapeRegexSymbols(CONTENT_ATTR), "g"); + private attrSanitizer = /-/g; + + private replaceNgAttribute(input: string, componentId: string): string { + return input.replace(this.attrReplacer, + "_ng_content_" + componentId.replace(this.attrSanitizer, "_")); + } + renderComponent(componentProto: RenderComponentType): Renderer { return this._rootRenderer.renderComponent(componentProto); } @@ -175,13 +185,14 @@ export class NativeScriptRenderer extends Renderer { public createElement(parentElement: util.NgView, name: string): util.NgView { util.traceLog('NativeScriptRenderer.createElement: ' + name + ' parent: ' + parentElement + ', ' + (parentElement ? parentElement.nodeName : 'null')); - let result = util.createView(name, parentElement); - // adding an attribute (property) to {N} view for applying component specific css. - // The property value is generated by angular2 infrastructure on conponent creation. - if (this.hasComponentStyles) { - result[CONTENT_ATTR.replace(COMPONENT_VARIABLE, this.componentProtoId)] = true; - } - return result; + return util.createView(name, parentElement, (view) => { + // Set an attribute to the view to scope component-specific css. + // The property name is pre-generated by Angular. + if (this.hasComponentStyles) { + const cssAttribute = this.replaceNgAttribute(CONTENT_ATTR, this.componentProtoId); + view[cssAttribute] = true; + } + }); } public createText(value: string): util.NgView { diff --git a/src/nativescript-angular/view-util.ts b/src/nativescript-angular/view-util.ts index e56263871..b141002ba 100644 --- a/src/nativescript-angular/view-util.ts +++ b/src/nativescript-angular/view-util.ts @@ -84,22 +84,27 @@ export function getChildIndex(parent: any, child: NgView) { } } -function createAndAttach(name: string, viewClass: ViewClass, parent: NgView): NgView { +function createAndAttach(name: string, viewClass: ViewClass, parent: NgView, beforeAttach?: BeforeAttachAction): NgView { const view = new viewClass(); view.nodeName = name; view.meta = getViewMeta(name); + if (beforeAttach) { + beforeAttach(view); + } if (parent) { insertChild(parent, view); } return view; } -export function createView(name: string, parent: NgView): NgView { +export type BeforeAttachAction = (view: View) => void; + +export function createView(name: string, parent: NgView, beforeAttach?: BeforeAttachAction): NgView { if (isKnownView(name)) { const viewClass = getViewClass(name); - return createAndAttach(name, viewClass, parent); + return createAndAttach(name, viewClass, parent, beforeAttach); } else { - return createViewContainer(name, parent); + return createViewContainer(name, parent, beforeAttach); } } @@ -111,11 +116,11 @@ export function createText(value: string): NgView { return text; } -export function createViewContainer(name: string, parentElement: NgView) { +export function createViewContainer(name: string, parentElement: NgView, beforeAttach: BeforeAttachAction) { //HACK: Using a ContentView here, so that it creates a native View object traceLog('Creating view container in:' + parentElement); - const layout = createView('ProxyViewContainer', parentElement); + const layout = createView('ProxyViewContainer', parentElement, beforeAttach); layout.nodeName = 'ProxyViewContainer'; return layout; } diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index 72a14cead..f5a937c2d 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -8,6 +8,7 @@ import {ProxyViewContainer} from "ui/proxy-view-container"; import {Red} from "color/known-colors"; import {dumpView} from "./test-utils"; import {TestApp} from "./test-app"; +import {LayoutBase} from "ui/layouts/layout-base" @Component({ template: `` @@ -63,6 +64,27 @@ export class StyledLabelCmp { } } +@Component({ + selector: "styled-label-cmp2", + styles: [ + `Label { color: red; }`, + ` + StackLayout { color: brick; } + TextField { color: red; background-color: lime; } + `, + ], + template: ` + + + + + ` +}) +export class StyledLabelCmp2 { + constructor(public elementRef: ElementRef) { + } +} + @Component({ selector: "ng-if-label", template: `` @@ -122,7 +144,7 @@ describe('Renderer E2E', () => { }); }); - it("applies component styles", () => { + it("applies component styles from single source", () => { return testApp.loadComponent(StyledLabelCmp).then((componentRef) => { const componentRoot = componentRef.instance.elementRef.nativeElement; const label = (componentRoot).getChildAt(0); @@ -130,6 +152,20 @@ describe('Renderer E2E', () => { }); }); + it("applies component styles from multiple sources", () => { + return testApp.loadComponent(StyledLabelCmp2).then((componentRef) => { + const componentRoot = componentRef.instance.elementRef.nativeElement; + const layout = (componentRoot).getChildAt(0); + + const label = (layout).getChildAt(0); + assert.equal(Red, label.style.color.hex); + + const textField = (layout).getChildAt(1); + console.log("TEXT style.color: " + textField.style.color); + assert.equal(Red, textField.style.color.hex); + }); + }); + describe("Structural directives", () => { it("ngIf hides component when false", () => { return testApp.loadComponent(NgIfLabel).then((componentRef) => { @@ -180,4 +216,4 @@ describe('Renderer E2E', () => { }); }); }) -}) \ No newline at end of file +}) From 44d0430deedc60d46a971f7400dc3f5f59411c6a Mon Sep 17 00:00:00 2001 From: Hristo Deshev Date: Mon, 21 Mar 2016 17:17:10 +0200 Subject: [PATCH 2/2] Bump version to 0.0.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38769dc94..b93f03d7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nativescript-angular", - "version": "0.0.36", + "version": "0.0.37", "description": "", "homepage": "http://www.telerik.com", "bugs": "http://www.telerik.com",