Skip to content

Fix multiple component styles #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
27 changes: 19 additions & 8 deletions src/nativescript-angular/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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 {
Expand Down
17 changes: 11 additions & 6 deletions src/nativescript-angular/view-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <NgView>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);
}
}

Expand All @@ -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;
}
Expand Down
40 changes: 38 additions & 2 deletions tests/app/tests/renderer-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `<StackLayout><Label text="Layout"></Label></StackLayout>`
Expand Down Expand Up @@ -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: `
<StackLayout orientation="horizontal">
<Label text="Styled!"></Label>
<TextField text="Styled too!"></TextField>
</StackLayout>
`
})
export class StyledLabelCmp2 {
constructor(public elementRef: ElementRef) {
}
}

@Component({
selector: "ng-if-label",
template: `<Label *ngIf="show" text="iffed"></Label>`
Expand Down Expand Up @@ -122,14 +144,28 @@ 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 = (<ProxyViewContainer>componentRoot).getChildAt(0);
assert.equal(Red, label.style.color.hex);
});
});

it("applies component styles from multiple sources", () => {
return testApp.loadComponent(StyledLabelCmp2).then((componentRef) => {
const componentRoot = componentRef.instance.elementRef.nativeElement;
const layout = (<ProxyViewContainer>componentRoot).getChildAt(0);

const label = (<LayoutBase>layout).getChildAt(0);
assert.equal(Red, label.style.color.hex);

const textField = (<LayoutBase>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) => {
Expand Down Expand Up @@ -180,4 +216,4 @@ describe('Renderer E2E', () => {
});
});
})
})
})