diff --git a/ng-sample/.vscode/launch.json b/ng-sample/.vscode/launch.json
new file mode 100644
index 000000000..7d0ec5702
--- /dev/null
+++ b/ng-sample/.vscode/launch.json
@@ -0,0 +1,89 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Launch on iOS Device",
+ "type": "nativescript",
+ "platform": "ios",
+ "request": "launch",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "stopOnEntry": true,
+ "emulator": false
+ },
+ {
+ "name": "Attach on iOS Device",
+ "type": "nativescript",
+ "platform": "ios",
+ "request": "attach",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "emulator": false
+ },
+ {
+ "name": "Launch on iOS Emulator",
+ "type": "nativescript",
+ "platform": "ios",
+ "request": "launch",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "stopOnEntry": true,
+ "emulator": true
+ },
+ {
+ "name": "Attach on iOS Emulator",
+ "type": "nativescript",
+ "platform": "ios",
+ "request": "attach",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "emulator": true
+ },
+ {
+ "name": "Launch on Android Device",
+ "type": "nativescript",
+ "platform": "android",
+ "request": "launch",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "stopOnEntry": true,
+ "emulator": false
+ },
+ {
+ "name": "Launch on Android Emulator",
+ "type": "nativescript",
+ "platform": "android",
+ "request": "launch",
+ "appRoot": ".",
+ "sourceMaps": true,
+ "diagnosticLogging": true,
+ "stopOnEntry": true,
+ "emulator": true
+ },
+ {
+ "name": "Attach on Android Device",
+ "type": "nativescript",
+ "platform": "android",
+ "request": "attach",
+ "appRoot": ".",
+ "sourceMaps": false,
+ "diagnosticLogging": true,
+ "emulator": false
+ },
+ {
+ "name": "Attach on Android Emulator",
+ "type": "nativescript",
+ "platform": "android",
+ "request": "attach",
+ "appRoot": ".",
+ "sourceMaps": false,
+ "diagnosticLogging": true,
+ "emulator": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ng-sample/.vscode/settings.json b/ng-sample/.vscode/settings.json
new file mode 100644
index 000000000..c3899ddb9
--- /dev/null
+++ b/ng-sample/.vscode/settings.json
@@ -0,0 +1,11 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+ "files.exclude": {
+ "**/*.js": {
+ "when": "$(basename).ts"
+ },
+ "**/*.js.map": {},
+ "platforms/**": {},
+ "hooks/**": {}
+ }
+}
\ No newline at end of file
diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts
index 4e5f5edd2..3dde0b20d 100644
--- a/ng-sample/app/app.ts
+++ b/ng-sample/app/app.ts
@@ -11,7 +11,9 @@ import { NS_ROUTER_PROVIDERS, routerTraceCategory } from "./nativescript-angular
import { rendererTraceCategory } from "./nativescript-angular/renderer";
import trace = require("trace");
-trace.setCategories(routerTraceCategory + ", " + rendererTraceCategory);
+// trace.setCategories(routerTraceCategory + ", " + rendererTraceCategory);
+// trace.setCategories(rendererTraceCategory);
+// trace.setCategories(routerTraceCategory);
trace.enable();
import {RendererTest} from './examples/renderer-test';
@@ -20,11 +22,16 @@ import {ListTest} from './examples/list/list-test';
import {ListTestAsync} from "./examples/list/list-test-async";
import {ImageTest} from "./examples/image/image-test";
import {NavigationTest} from "./examples/navigation/navigation-test";
+import {ActionBarTest} from "./examples/action-bar/action-bar-test";
-//nativeScriptBootstrap(RendererTest);
-//nativeScriptBootstrap(Benchmark);
-//nativeScriptBootstrap(ListTest);
-nativeScriptBootstrap(ListTestAsync);
+// nativeScriptBootstrap(RendererTest);
+// nativeScriptBootstrap(Benchmark);
+// nativeScriptBootstrap(ListTest);
+// nativeScriptBootstrap(ListTestAsync);
+// nativeScriptBootstrap(Benchmark);
+// nativeScriptBootstrap(ListTest);
+// nativeScriptBootstrap(ListTestAsync);
// nativeScriptBootstrap(ImageTest);
-//nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]);
+// nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]);
+nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS], { startPageActionBarHidden: false });
diff --git a/ng-sample/app/examples/action-bar/action-bar-test.ts b/ng-sample/app/examples/action-bar/action-bar-test.ts
new file mode 100644
index 000000000..3572fa82b
--- /dev/null
+++ b/ng-sample/app/examples/action-bar/action-bar-test.ts
@@ -0,0 +1,92 @@
+import {Component} from 'angular2/core';
+import {RouteConfig} from 'angular2/router';
+import { Page} from "ui/page";
+import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "../../nativescript-angular/router/ns-router";
+import {NS_DIRECTIVES} from "../../nativescript-angular/directives/ns-directives";
+
+@Component({
+ selector: "first",
+ directives: [NS_ROUTER_DIRECTIVES, NS_DIRECTIVES],
+ template: `
+
+
+
+
+
+
+
+
+ `,
+})
+class FirstComponent {
+ public show: boolean = true;
+ onTap() {
+ console.log("FirstComponent.Tapped!");
+ }
+}
+
+
+@Component({
+ selector: "nested-componenet",
+ directives: [NS_ROUTER_DIRECTIVES, NS_DIRECTIVES],
+ template: `
+
+
+
+
+
+
+
+
+
+
+ `,
+})
+class NestedComponent {
+ public show: boolean = true;
+
+ onTap() {
+ console.log("NestedComponent.Tapped!");
+ }
+}
+
+@Component({
+ selector: "second",
+ directives: [NS_ROUTER_DIRECTIVES, NS_DIRECTIVES, NestedComponent],
+ template: `
+
+
+
+
+
+
+
+
+
+ `,
+})
+class SecondComponent {
+ onTap() {
+ console.log("SecondComponent.Tapped!");
+ }
+}
+
+
+
+@Component({
+ selector: 'action-bar-test',
+ directives: [NS_ROUTER_DIRECTIVES],
+ template: `
+
+
+
+ `
+})
+@RouteConfig([
+ { path: '/', component: FirstComponent, as: 'First' },
+ { path: '/second', component: SecondComponent, as: 'Second' },
+])
+export class ActionBarTest {
+}
+
+
diff --git a/src/nativescript-angular/application.d.ts b/src/nativescript-angular/application.d.ts
index 89d8035eb..58f0af33d 100644
--- a/src/nativescript-angular/application.d.ts
+++ b/src/nativescript-angular/application.d.ts
@@ -1,5 +1,10 @@
import { Type, ApplicationRef, Provider } from 'angular2/core';
+export interface AppOptions {
+ cssFile?: string;
+ startPageActionBarHidden?: boolean;
+}
+
export type BindingArray = Array>;
export function bootstrap(appComponentType: any, componentInjectableBindings?: BindingArray): Promise;
export function nativeScriptBootstrap(appComponentType: any, customProviders?: BindingArray, appOptions?: any): void;
diff --git a/src/nativescript-angular/application.ts b/src/nativescript-angular/application.ts
index eddf3f24a..cdb1aca84 100644
--- a/src/nativescript-angular/application.ts
+++ b/src/nativescript-angular/application.ts
@@ -43,8 +43,13 @@ import {defaultPageProvider} from "./platform-providers";
let _platform = null;
+export interface AppOptions {
+ cssFile?: string;
+ startPageActionBarHidden?: boolean;
+}
+
export function bootstrap(appComponentType: any,
- customProviders: ProviderArray = null) : Promise {
+ customProviders: ProviderArray = null): Promise {
NativeScriptDomAdapter.makeCurrent();
let platformProviders: ProviderArray = [
@@ -72,21 +77,24 @@ export function bootstrap(appComponentType: any,
if (isPresent(customProviders)) {
appProviders.push(customProviders);
}
-
+
if (!_platform) {
_platform = platform(platformProviders);
}
return _platform.application(appProviders).bootstrap(appComponentType);
}
-export function nativeScriptBootstrap(appComponentType: any, customProviders?: ProviderArray, appOptions?: any) {
+export function nativeScriptBootstrap(appComponentType: any, customProviders?: ProviderArray, appOptions?: AppOptions) {
if (appOptions && appOptions.cssFile) {
application.cssFile = appOptions.cssFile;
}
application.start({
create: (): Page => {
let page = new Page();
-
+ if (appOptions) {
+ page.actionBarHidden = appOptions.startPageActionBarHidden;
+ }
+
let onLoadedHandler = function(args) {
page.off('loaded', onLoadedHandler);
//profiling.stop('application-start');
@@ -97,7 +105,7 @@ export function nativeScriptBootstrap(appComponentType: any, customProviders?: P
bootstrap(appComponentType, customProviders).then((appRef) => {
//profiling.stop('ng-bootstrap');
console.log('ANGULAR BOOTSTRAP DONE.');
- }, (err) =>{
+ }, (err) => {
console.log('ERROR BOOTSTRAPPING ANGULAR');
let errorMessage = err.message + "\n\n" + err.stack;
console.log(errorMessage);
@@ -107,9 +115,9 @@ export function nativeScriptBootstrap(appComponentType: any, customProviders?: P
page.content = view;
});
}
-
+
page.on('loaded', onLoadedHandler);
-
+
return page;
}
});
diff --git a/src/nativescript-angular/directives/action-bar.ts b/src/nativescript-angular/directives/action-bar.ts
new file mode 100644
index 000000000..b861defdf
--- /dev/null
+++ b/src/nativescript-angular/directives/action-bar.ts
@@ -0,0 +1,128 @@
+import {Directive, Component, ContentChildren, ElementRef, Optional} from 'angular2/core';
+import {ActionItem, ActionBar, NavigationButton} from "ui/action-bar";
+import {isBlank} from "angular2/src/facade/lang";
+import {Page} from "ui/page";
+import {View} from 'ui/core/view';
+import {registerElement, ViewClassMeta, NgView } from '../element-registry';
+
+var actionBarMeta: ViewClassMeta = {
+ skipAddToDom: true,
+ insertChild: (parent: NgView, child: NgView, atIndex: number) => {
+ const bar = (parent);
+ const childView = child;
+
+ if (child instanceof NavigationButton) {
+ bar.navigationButton = childView;
+ childView.parent = bar;
+ } else if (child instanceof ActionItem) {
+ bar.actionItems.addItem(childView);
+ childView.parent = bar;
+ } else if (child.nodeName === "template") {
+ child.templateParent = parent;
+ } else if (child.nodeName !== "#text" && child instanceof View) {
+ bar.titleView = childView;
+ }
+ },
+ removeChild: (parent: NgView, child: NgView) => {
+ const bar = (parent);
+ const childView = child;
+ if (child instanceof NavigationButton) {
+ if (bar.navigationButton === childView) {
+ bar.navigationButton = null;
+ }
+ childView.parent = null;
+ } else if (child instanceof ActionItem) {
+ bar.actionItems.removeItem(childView);
+ childView.parent = null;
+ } else if (child.nodeName !== "template" && child instanceof View && bar.titleView && bar.titleView === childView) {
+ bar.titleView = null;
+ }
+ },
+}
+
+registerElement("ActionBar", () => require("ui/action-bar").ActionBar, actionBarMeta);
+registerElement("ActionItem", () => require("ui/action-bar").ActionItem);
+registerElement("NavigationButton", () => require("ui/action-bar").NavigationButton);
+
+@Component({
+ selector: "ActionBar",
+ template: ""
+})
+export class ActionBarComponent {
+ constructor(public element: ElementRef, private page: Page) {
+ }
+
+ ngOnInit() {
+ if (isBlank(this.page.actionBarHidden)) {
+ this.page.actionBarHidden = false;
+ }
+ this.page.actionBar = this.element.nativeElement;
+ this.page.actionBar.update();
+ }
+}
+
+@Component({
+ selector: "ActionBarExtension",
+ template: ""
+})
+export class ActionBarScope {
+ constructor(private page: Page) {
+ }
+
+ public onNavButtonInit(navBtn: NavigationButtonDirective) {
+ this.page.actionBar.navigationButton = navBtn.element.nativeElement;
+ }
+
+ public onNavButtonDestroy(navBtn: NavigationButtonDirective) {
+ const nav = navBtn.element.nativeElement;
+ if (nav && this.page.actionBar.navigationButton === nav) {
+ this.page.actionBar.navigationButton = null;
+ }
+ }
+
+ public onActionInit(item: ActionItemDirective) {
+ this.page.actionBar.actionItems.addItem(item.element.nativeElement);
+ }
+
+ public onActionDestroy(item: ActionItemDirective) {
+ this.page.actionBar.actionItems.removeItem(item.element.nativeElement);
+ }
+}
+
+@Directive({
+ selector: "ActionItem"
+})
+export class ActionItemDirective {
+ constructor(public element: ElementRef, @Optional() private ownerScope: ActionBarScope) {
+ }
+
+ ngOnInit() {
+ if (this.ownerScope) {
+ this.ownerScope.onActionInit(this);
+ }
+ }
+ ngOnDestroy() {
+ if (this.ownerScope) {
+ this.ownerScope.onActionDestroy(this);
+ }
+ }
+}
+
+@Directive({
+ selector: "NavigationButton"
+})
+export class NavigationButtonDirective {
+ constructor(public element: ElementRef, @Optional() private ownerScope: ActionBarScope) {
+ }
+
+ ngOnInit() {
+ if (this.ownerScope) {
+ this.ownerScope.onNavButtonInit(this);
+ }
+ }
+ ngOnDestroy() {
+ if (this.ownerScope) {
+ this.ownerScope.onNavButtonDestroy(this);
+ }
+ }
+}
diff --git a/src/nativescript-angular/directives/ns-directives.ts b/src/nativescript-angular/directives/ns-directives.ts
index 7fc4e467b..031f599d2 100644
--- a/src/nativescript-angular/directives/ns-directives.ts
+++ b/src/nativescript-angular/directives/ns-directives.ts
@@ -3,6 +3,7 @@ import {ListViewComponent} from './list-view-comp';
import {TextValueAccessor} from '../value-accessors/text-value-accessor';
import {CheckedValueAccessor} from '../value-accessors/checked-value-accessor';
import {TabViewDirective, TabViewItemDirective} from './tab-view';
+import {ActionBarComponent, ActionBarScope, ActionItemDirective, NavigationButtonDirective} from './action-bar';
export const NS_DIRECTIVES: Type[] = [
ListViewComponent,
@@ -11,5 +12,10 @@ export const NS_DIRECTIVES: Type[] = [
TabViewItemDirective,
TextValueAccessor,
- CheckedValueAccessor
+ CheckedValueAccessor,
+
+ ActionBarComponent,
+ ActionBarScope,
+ ActionItemDirective,
+ NavigationButtonDirective
];
diff --git a/src/nativescript-angular/element-registry.d.ts b/src/nativescript-angular/element-registry.d.ts
index 5f2581fa4..6fda71a9b 100644
--- a/src/nativescript-angular/element-registry.d.ts
+++ b/src/nativescript-angular/element-registry.d.ts
@@ -2,10 +2,27 @@ import {View} from 'ui/core/view';
export type ViewResolver = () => ViewClass;
+export type NgView = View & ViewExtensions;
+
+export interface ViewExtensions {
+ nodeName: string;
+ templateParent: NgView;
+ cssClasses: Map;
+ meta: ViewClassMeta;
+}
+
+export interface ViewClassMeta {
+ skipAddToDom?: boolean;
+ insertChild?: (parent: NgView, child: NgView, atIndex: number) => void;
+ removeChild?: (parent: NgView, child: NgView) => void;
+}
+
export interface ViewClass {
new(): View
}
+
export function registerElement(elementName: string, resolver: ViewResolver): void;
export function getViewClass(elementName: string): ViewClass;
export function isKnownView(elementName: string): boolean;
+export function getViewMeta(nodeName: string): ViewClassMeta;
\ No newline at end of file
diff --git a/src/nativescript-angular/element-registry.ts b/src/nativescript-angular/element-registry.ts
index f1726be60..7e78c6aa7 100644
--- a/src/nativescript-angular/element-registry.ts
+++ b/src/nativescript-angular/element-registry.ts
@@ -1,74 +1,101 @@
import {View} from 'ui/core/view';
+export type ViewResolver = () => ViewClass;
+export type NgView = View & ViewExtensions;
+
+export interface ViewClassMeta {
+ skipAddToDom?: boolean;
+ insertChild?: (parent: NgView, child: NgView, atIndex: number) => void;
+ removeChild?: (parent: NgView, child: NgView) => void;
+}
+
+export interface ViewExtensions {
+ nodeName: string;
+ templateParent: NgView;
+ cssClasses: Map;
+ meta: ViewClassMeta;
+}
+
export interface ViewClass {
- new(): View
+ new (): View
}
-export type ViewResolver = () => ViewClass;
+var defaultViewMeta: ViewClassMeta = {
+ skipAddToDom: false,
+}
-var elementMap: Map = new Map();
+var elementMap: Map = new Map();
-export function registerElement(elementName: string, resolver: ViewResolver): void {
+export function registerElement(elementName: string, resolver: ViewResolver, meta?: ViewClassMeta): void {
if (elementMap.has(elementName)) {
throw new Error(`Element for ${elementName} already registered.`);
} else {
- elementMap.set(elementName, resolver);
- elementMap.set(elementName.toLowerCase(), resolver);
+ const entry = { resolver: resolver, meta: meta };
+ elementMap.set(elementName, entry);
+ elementMap.set(elementName.toLowerCase(), entry);
}
}
export function getViewClass(elementName: string): ViewClass {
- const resolver = elementMap.get(elementName) ||
- elementMap.get(elementName.toLowerCase());
- if (!resolver) {
+ const entry = elementMap.get(elementName) ||
+ elementMap.get(elementName.toLowerCase());
+ if (!entry) {
throw new TypeError(`No known component for element ${elementName}.`);
}
try {
- return resolver();
+ return entry.resolver();
} catch (e) {
- throw new TypeError(`Could not load view for: ${elementName}.
+ throw new TypeError(`Could not load view for: ${elementName}.${e}`);
+ }
+}
-${e}`);
+export function getViewMeta(nodeName: string): ViewClassMeta {
+ let meta = defaultViewMeta;
+ const entry = elementMap.get(nodeName) || elementMap.get(nodeName.toLowerCase());
+ if (entry && entry.meta) {
+ meta = entry.meta;
}
+ return meta;
}
export function isKnownView(elementName: string): boolean {
return elementMap.has(elementName) ||
- elementMap.has(elementName.toLowerCase());
+ elementMap.has(elementName.toLowerCase());
}
+
+
//Register default NativeScript components
+//Note: ActionBar related components are registerd together with action-bar directives.
registerElement("AbsoluteLayout", () => require("ui/layouts/absolute-layout").AbsoluteLayout);
-registerElement("ActionBar", () => require("ui/action-bar").ActionBar);
-registerElement("ActionItem", () => require("ui/action-bar").ActionItem);
-registerElement("ActivityIndicator", () => require("ui/activity-indicator").ActivityIndicator);
-registerElement("Border", () => require("ui/border").Border);
-registerElement("Button", () => require("ui/button").Button);
-registerElement("ContentView", () => require("ui/content-view").ContentView);
-registerElement("DatePicker", () => require("ui/date-picker").DatePicker);
-registerElement("DockLayout", () => require("ui/layouts/dock-layout").DockLayout);
-registerElement("GridLayout", () => require("ui/layouts/grid-layout").GridLayout);
-registerElement("HtmlView", () => require("ui/html-view").HtmlView);
-registerElement("Image", () => require("ui/image").Image);
+registerElement("ActivityIndicator", () => require("ui/activity-indicator").ActivityIndicator);
+registerElement("Border", () => require("ui/border").Border);
+registerElement("Button", () => require("ui/button").Button);
+registerElement("ContentView", () => require("ui/content-view").ContentView);
+registerElement("DatePicker", () => require("ui/date-picker").DatePicker);
+registerElement("DockLayout", () => require("ui/layouts/dock-layout").DockLayout);
+registerElement("GridLayout", () => require("ui/layouts/grid-layout").GridLayout);
+registerElement("HtmlView", () => require("ui/html-view").HtmlView);
+registerElement("Image", () => require("ui/image").Image);
// Parse5 changes tags to
. WTF!
-registerElement("img", () => require("ui/image").Image);
-registerElement("Label", () => require("ui/label").Label);
-registerElement("ListPicker", () => require("ui/list-picker").ListPicker);
-registerElement("ListView", () => require("ui/list-view").ListView);
-registerElement("Page", () => require("ui/page").Page);
-registerElement("Placeholder", () => require("ui/placeholder").Placeholder);
-registerElement("Progress", () => require("ui/progress").Progress);
-registerElement("Repeater", () => require("ui/repeater").Repeater);
-registerElement("ScrollView", () => require("ui/scroll-view").ScrollView);
-registerElement("SearchBar", () => require("ui/search-bar").SearchBar);
-registerElement("SegmentedBar", () => require("ui/segmented-bar").SegmentedBar);
-registerElement("Slider", () => require("ui/slider").Slider);
-registerElement("StackLayout", () => require("ui/layouts/stack-layout").StackLayout);
-registerElement("Switch", () => require("ui/switch").Switch);
-registerElement("TabView", () => require("ui/tab-view").TabView);
-registerElement("TextField", () => require("ui/text-field").TextField);
-registerElement("TextView", () => require("ui/text-view").TextView);
-registerElement("TimePicker", () => require("ui/time-picker").TimePicker);
-registerElement("WebView", () => require("ui/web-view").WebView);
-registerElement("WrapLayout", () => require("ui/layouts/wrap-layout").WrapLayout);
-registerElement("ProxyViewContainer", () => require("ui/proxy-view-container").ProxyViewContainer);
+registerElement("img", () => require("ui/image").Image);
+registerElement("Label", () => require("ui/label").Label);
+registerElement("ListPicker", () => require("ui/list-picker").ListPicker);
+registerElement("ListView", () => require("ui/list-view").ListView);
+registerElement("Page", () => require("ui/page").Page);
+registerElement("Placeholder", () => require("ui/placeholder").Placeholder);
+registerElement("Progress", () => require("ui/progress").Progress);
+registerElement("ProxyViewContainer", () => require("ui/proxy-view-container").ProxyViewContainer);
+registerElement("Repeater", () => require("ui/repeater").Repeater);
+registerElement("ScrollView", () => require("ui/scroll-view").ScrollView);
+registerElement("SearchBar", () => require("ui/search-bar").SearchBar);
+registerElement("SegmentedBar", () => require("ui/segmented-bar").SegmentedBar);
+registerElement("Slider", () => require("ui/slider").Slider);
+registerElement("StackLayout", () => require("ui/layouts/stack-layout").StackLayout);
+registerElement("Switch", () => require("ui/switch").Switch);
+registerElement("TabView", () => require("ui/tab-view").TabView);
+registerElement("TextField", () => require("ui/text-field").TextField);
+registerElement("TextView", () => require("ui/text-view").TextView);
+registerElement("TimePicker", () => require("ui/time-picker").TimePicker);
+registerElement("WebView", () => require("ui/web-view").WebView);
+registerElement("WrapLayout", () => require("ui/layouts/wrap-layout").WrapLayout);
diff --git a/src/nativescript-angular/router/page-router-outlet.ts b/src/nativescript-angular/router/page-router-outlet.ts
index 28d7e967b..9a4175f62 100644
--- a/src/nativescript-angular/router/page-router-outlet.ts
+++ b/src/nativescript-angular/router/page-router-outlet.ts
@@ -273,6 +273,7 @@ class PageShim implements OnActivate, OnDeactivate, CanReuse, OnReuse {
private id: number;
private isInitialized: boolean;
private componentRef: ComponentRef;
+ private page: Page;
constructor(
private element: ElementRef,
@@ -282,6 +283,7 @@ class PageShim implements OnActivate, OnDeactivate, CanReuse, OnReuse {
) {
this.id = PageShim.pageShimCount++;
this.log("constructor");
+ this.page = new Page();
}
routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any {
@@ -295,7 +297,12 @@ class PageShim implements OnActivate, OnDeactivate, CanReuse, OnReuse {
if (!this.isInitialized) {
result = new Promise((resolve, reject) => {
this.isInitialized = true;
- this.loader.loadIntoLocation(this.componentType, this.element, 'content')
+
+ let providers = Injector.resolve([
+ provide(Page, { useValue: this.page }),
+ ]);
+
+ this.loader.loadIntoLocation(this.componentType, this.element, 'content', providers)
.then((componentRef) => {
this.componentRef = componentRef;
@@ -309,7 +316,7 @@ class PageShim implements OnActivate, OnDeactivate, CanReuse, OnReuse {
topmost().navigate({
animated: true,
create: () => {
- const page = new Page();
+ const page = this.page;
page.on('loaded', () => {
// Finish activation when page is fully loaded.
resolve()
diff --git a/src/nativescript-angular/view-util.ts b/src/nativescript-angular/view-util.ts
index d38d0b16a..bf6a6b99a 100644
--- a/src/nativescript-angular/view-util.ts
+++ b/src/nativescript-angular/view-util.ts
@@ -3,22 +3,20 @@ import {View} from "ui/core/view";
import {Placeholder} from "ui/placeholder";
import {ContentView} from 'ui/content-view';
import {LayoutBase} from 'ui/layouts/layout-base';
-import {ViewClass, getViewClass, isKnownView} from './element-registry';
+import {ViewClass, getViewClass, getViewMeta, isKnownView, ViewExtensions, NgView, ViewClassMeta} from './element-registry';
import {getSpecialPropertySetter} from "ui/builder/special-properties";
+import { ActionBar, ActionItem, NavigationButton } from "ui/action-bar";
import trace = require("trace");
+
export const rendererTraceCategory = "ns-renderer";
export function traceLog(msg) {
trace.write(msg, rendererTraceCategory);
}
-export interface ViewExtensions {
- nodeName: string;
- templateParent: NgView;
- cssClasses: Map;
-}
+export type ViewExtensions = ViewExtensions;
+export type NgView = NgView;
-export type NgView = View & ViewExtensions;
export type NgLayoutBase = LayoutBase & ViewExtensions;
export type NgContentView = ContentView & ViewExtensions;
@@ -34,13 +32,14 @@ export function isContentView(view: any): view is NgContentView {
return view instanceof ContentView;
}
-function isComplexProperty(view: NgView) {
- const name = view.nodeName
- return isString(name) && name.indexOf(".") !== -1;
-}
-
export function insertChild(parent: any, child: NgView, atIndex = -1) {
- if (isLayout(parent)) {
+ if (!parent || child.meta.skipAddToDom) {
+ return;
+ }
+
+ if (parent.meta && parent.meta.insertChild) {
+ parent.meta.insertChild(parent, child, atIndex);
+ } else if (isLayout(parent)) {
if (atIndex !== -1) {
parent.insertChild(child, atIndex);
} else {
@@ -48,13 +47,21 @@ export function insertChild(parent: any, child: NgView, atIndex = -1) {
}
} else if (isContentView(parent)) {
parent.content = child;
+ } else if (parent && parent._addChildFromBuilder) {
+ parent._addChildFromBuilder(child.nodeName, child);
} else {
//throw new Error("Parent can't contain children: " + parent.nodeName + ', ' + parent);
}
}
export function removeChild(parent: any, child: NgView) {
- if (isLayout(parent)) {
+ if (!parent || child.meta.skipAddToDom) {
+ return;
+ }
+
+ if (parent.meta && parent.meta.removeChild) {
+ parent.meta.removeChild(parent, child);
+ } else if (isLayout(parent)) {
parent.removeChild(child);
} else if (isContentView(parent)) {
if (parent.content === child) {
@@ -80,6 +87,7 @@ export function getChildIndex(parent: any, child: NgView) {
function createAndAttach(name: string, viewClass: ViewClass, parent: NgView): NgView {
const view = new viewClass();
view.nodeName = name;
+ view.meta = getViewMeta(name);
if (parent) {
insertChild(parent, view);
}
@@ -99,6 +107,7 @@ export function createText(value: string): NgView {
const text = new Placeholder();
text.nodeName = "#text";
text.visibility = "collapse";
+ text.meta = getViewMeta("Placeholder");
return text;
}
@@ -113,7 +122,7 @@ export function createViewContainer(name: string, parentElement: NgView) {
export function createTemplateAnchor(parentElement: NgView) {
//HACK: Using a ContentView here, so that it creates a native View object
- const anchor = createAndAttach('ContentView', ContentView, parentElement);
+ const anchor = createAndAttach('template', ContentView, parentElement);
anchor.visibility = "collapse";
anchor.templateParent = parentElement;
return anchor;
diff --git a/tests/app/tests/property-sets.ts b/tests/app/tests/property-sets.ts
index b39b73d49..168e800e4 100644
--- a/tests/app/tests/property-sets.ts
+++ b/tests/app/tests/property-sets.ts
@@ -3,12 +3,14 @@ import {assert} from "./test-config";
import {bootstrap} from "../nativescript-angular/application";
import {Component} from "angular2/core";
import {View} from "ui/core/view";
-import {NgView, ViewExtensions, setProperty} from "../nativescript-angular/view-util";
+import {setProperty} from "../nativescript-angular/view-util";
+import {NgView, ViewExtensions, ViewClassMeta} from "../nativescript-angular/element-registry";
import {Red} from "color/known-colors";
class TestView extends View implements ViewExtensions {
public nodeName: string = "TestView";
public templateParent: NgView = null;
+ public meta: ViewClassMeta = { skipAddToDom: false };
public cssClasses: Map = new Map();
public stringValue: string = "";