Skip to content
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
28 changes: 19 additions & 9 deletions nativescript-angular/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Inject, Injectable, Optional} from '@angular/core/src/di';
import {Inject, Injectable, Optional, NgZone} from '@angular/core';
import {
Renderer,
RootRenderer,
Expand Down Expand Up @@ -28,7 +28,9 @@ export class NativeScriptRootRenderer implements RootRenderer {
constructor(
@Optional() @Inject(APP_ROOT_VIEW) private _rootView: View,
@Inject(DEVICE) device: Device,
private _animationDriver: AnimationDriver) {
private _animationDriver: AnimationDriver,
private _zone: NgZone) {

this._viewUtil = new ViewUtil(device);
}

Expand All @@ -52,7 +54,7 @@ export class NativeScriptRootRenderer implements RootRenderer {
renderComponent(componentProto: RenderComponentType): Renderer {
let renderer = this._registeredComponents.get(componentProto.id);
if (isBlank(renderer)) {
renderer = new NativeScriptRenderer(this, componentProto, this._animationDriver);
renderer = new NativeScriptRenderer(this, componentProto, this._animationDriver, this._zone);
this._registeredComponents.set(componentProto.id, renderer);
}
return renderer;
Expand All @@ -63,16 +65,18 @@ export class NativeScriptRootRenderer implements RootRenderer {
export class NativeScriptRenderer extends Renderer {
private componentProtoId: string;
private hasComponentStyles: boolean;
private rootRenderer: NativeScriptRootRenderer;

private get viewUtil(): ViewUtil {
return this.rootRenderer.viewUtil;
}

constructor(private _rootRenderer: NativeScriptRootRenderer, private componentProto: RenderComponentType, private animationDriver: AnimationDriver) {
constructor(
private rootRenderer: NativeScriptRootRenderer,
private componentProto: RenderComponentType,
private animationDriver: AnimationDriver,
private zone: NgZone) {

super();
this.rootRenderer = _rootRenderer;
let page = this.rootRenderer.page;
let stylesLength = componentProto.styles.length;
this.componentProtoId = componentProto.id;
for (let i = 0; i < stylesLength; i++) {
Expand All @@ -93,7 +97,7 @@ export class NativeScriptRenderer extends Renderer {
}

renderComponent(componentProto: RenderComponentType): Renderer {
return this._rootRenderer.renderComponent(componentProto);
return this.rootRenderer.renderComponent(componentProto);
}

selectRootElement(selector: string): NgView {
Expand Down Expand Up @@ -211,7 +215,13 @@ export class NativeScriptRenderer extends Renderer {

public listen(renderElement: NgView, eventName: string, callback: Function): Function {
traceLog('NativeScriptRenderer.listen: ' + eventName);
let zonedCallback = (<any>global).Zone.current.wrap(callback);
// Explicitly wrap in zone
let zonedCallback = (...args) => {
this.zone.run(() => {
callback.apply(undefined, args);
});
};

renderElement.on(eventName, zonedCallback);
if (eventName === View.loadedEvent && renderElement.isLoaded) {
const notifyData = { eventName: View.loadedEvent, object: renderElement };
Expand Down
49 changes: 44 additions & 5 deletions tests/app/tests/renderer-tests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//make sure you import mocha-config before @angular/core
import {assert} from "./test-config";
import {Component, ElementRef, Renderer} from "@angular/core";
import {Component, ElementRef, Renderer, NgZone} from "@angular/core";
import {ProxyViewContainer} from "ui/proxy-view-container";
import {Red} from "color/known-colors";
import {dumpView} from "./test-utils";
Expand Down Expand Up @@ -109,7 +109,8 @@ describe('Renderer E2E', () => {
before(() => {
return TestApp.create().then((app) => {
testApp = app;
})

});
});

after(() => {
Expand Down Expand Up @@ -163,6 +164,44 @@ describe('Renderer E2E', () => {
});
});

it("executes events inside NgZone when listen is called inside NgZone", (done) => {
const eventName = "someEvent";
const view = new StackLayout();
const evetArg = { eventName, object: view };
const callback = (arg) => {
assert.equal(arg, evetArg);
assert.isTrue(NgZone.isInAngularZone(), "Event should be executed inside NgZone");
done();
};

testApp.zone.run(() => {
testApp.renderer.listen(view, eventName, callback);
});

setTimeout(() => {
testApp.zone.runOutsideAngular(() => {
view.notify(evetArg);
});
}, 10);
});

it("executes events inside NgZone when listen is called outside NgZone", (done) => {
const eventName = "someEvent";
const view = new StackLayout();
const evetArg = { eventName, object: view };
const callback = (arg) => {
assert.equal(arg, evetArg);
assert.isTrue(NgZone.isInAngularZone(), "Event should be executed inside NgZone");
done();
};

testApp.zone.runOutsideAngular(() => {
testApp.renderer.listen(view, eventName, callback);

view.notify(evetArg);
});
});

describe("Structural directives", () => {
it("ngIf hides component when false", () => {
return testApp.loadComponent(NgIfLabel).then((componentRef) => {
Expand All @@ -180,7 +219,7 @@ describe('Renderer E2E', () => {
testApp.appRef.tick();
assert.equal("(ProxyViewContainer (template), (Label))", dumpView(componentRoot));
});
})
});

it("ngFor creates element for each item", () => {
return testApp.loadComponent(NgForLabel).then((componentRef) => {
Expand Down Expand Up @@ -212,8 +251,8 @@ describe('Renderer E2E', () => {
assert.equal("(ProxyViewContainer (template), (Label[text=one]), (Label[text=new]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true));
});
});
})
})
});
});

describe('Renderer createElement', () => {
let testApp: TestApp = null;
Expand Down
4 changes: 2 additions & 2 deletions tests/app/tests/style-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ describe("Setting style properties", () => {

beforeEach(() => {
const animationDriver = new NativeScriptAnimationDriver()
const rootRenderer = new NativeScriptRootRenderer(null, device, animationDriver);
const rootRenderer = new NativeScriptRootRenderer(null, device, animationDriver, null);
const componentType = new RenderComponentType("id", "templateUrl", 0,
null, []);
renderer = new NativeScriptRenderer(rootRenderer, componentType, animationDriver);
renderer = new NativeScriptRenderer(rootRenderer, componentType, animationDriver, null);
element = <NgView><any>new TextField();
});

Expand Down
25 changes: 13 additions & 12 deletions tests/app/tests/test-app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//make sure you import mocha-config before @angular/core
import {bootstrap, ProviderArray} from "nativescript-angular/application";
import {Type, Component, ComponentRef, DynamicComponentLoader,
ViewChild, ElementRef, provide, ApplicationRef, Renderer, ViewContainerRef
ViewChild, ElementRef, provide, ApplicationRef, Renderer, ViewContainerRef, NgZone
} from "@angular/core";

import {View} from "ui/core/view";
import {GridLayout} from "ui/layouts/grid-layout";
import {LayoutBase} from "ui/layouts/layout-base";
import {topmost} from 'ui/frame';
Expand All @@ -21,7 +20,8 @@ export class TestApp {
constructor(public loader: DynamicComponentLoader,
public elementRef: ViewContainerRef,
public appRef: ApplicationRef,
public renderer: Renderer) {
public renderer: Renderer,
public zone: NgZone) {
}

public loadComponent(type: Type): Promise<ComponentRef<any>> {
Expand Down Expand Up @@ -49,7 +49,7 @@ export class TestApp {
}
}

var runningApps = new Map<any, { hostView: LayoutBase, appRoot: GridLayout, appRef: ApplicationRef }>();
const runningApps = new Map<any, { hostView: LayoutBase, appRoot: GridLayout, appRef: ApplicationRef }>();

export function bootstrapTestApp<T>(appComponentType: new (...args) => T, providers: ProviderArray = []): Promise<T> {
const page = topmost().currentPage;
Expand All @@ -61,17 +61,18 @@ export function bootstrapTestApp<T>(appComponentType: new (...args) => T, provid
viewRoot.opacity = 0.7;
GridLayout.setRowSpan(rootLayout, 50);
GridLayout.setColumnSpan(rootLayout, 50);

const rootViewProvider = provide(APP_ROOT_VIEW, { useValue: viewRoot });
return bootstrap(appComponentType, providers.concat(rootViewProvider)).then((componentRef) => {
componentRef.injector.get(ApplicationRef)
componentRef.injector.get(ApplicationRef);
const testApp = componentRef.instance;

runningApps.set(testApp, {
hostView: rootLayout,
appRoot: viewRoot,
appRef: componentRef.injector.get(ApplicationRef) });


runningApps.set(testApp, {
hostView: rootLayout,
appRoot: viewRoot,
appRef: componentRef.injector.get(ApplicationRef)
});

return testApp;
});
}
Expand Down
2 changes: 1 addition & 1 deletion tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "2.1.1"
},
"tns-ios": {
"version": "2.0.1"
"version": "2.1.1"
}
},
"name": "ngtests",
Expand Down