From 87553093fe167aa3828dbc4c8de4cc2ecb4c7874 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Fri, 28 Oct 2016 14:36:58 +0300 Subject: [PATCH] Support for custom page factory providers --- nativescript-angular/directives/dialogs.ts | 9 +++-- nativescript-angular/platform-providers.ts | 19 ++++++++-- nativescript-angular/platform.ts | 23 ++++++++---- .../router/page-router-outlet.ts | 37 ++++++++++--------- ng-sample/app/app.ts | 25 ++++++++++--- ng-sample/package.json | 1 + 6 files changed, 77 insertions(+), 37 deletions(-) diff --git a/nativescript-angular/directives/dialogs.ts b/nativescript-angular/directives/dialogs.ts index 4c4ce8a14..892b0e9be 100644 --- a/nativescript-angular/directives/dialogs.ts +++ b/nativescript-angular/directives/dialogs.ts @@ -5,6 +5,7 @@ import { import { Page } from 'ui/page'; import { View } from 'ui/core/view'; import { DetachedLoader } from '../common/detached-loader'; +import { PageFactory, PAGE_FACTORY } from '../platform-providers'; export interface ModalDialogOptions { context?: any; @@ -36,9 +37,10 @@ export class ModalDialogService { const parentPage: Page = viewContainerRef.injector.get(Page); const resolver: ComponentFactoryResolver = viewContainerRef.injector.get(ComponentFactoryResolver); + const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY); return new Promise((resolve, reject) => { - setTimeout(() => ModalDialogService.showDialog(type, options, resolve, viewContainerRef, resolver, parentPage), 10); + setTimeout(() => ModalDialogService.showDialog(type, options, resolve, viewContainerRef, resolver, parentPage, pageFactory), 10); }); } @@ -48,9 +50,10 @@ export class ModalDialogService { doneCallback, containerRef: ViewContainerRef, resolver: ComponentFactoryResolver, - parentPage: Page): void { + parentPage: Page, + pageFactory: PageFactory): void { - const page = new Page(); + const page = pageFactory({ isModal: true, componentType: type }); let detachedLoaderRef: ComponentRef; const closeCallback = (...args) => { diff --git a/nativescript-angular/platform-providers.ts b/nativescript-angular/platform-providers.ts index bdd44120f..4635de4df 100644 --- a/nativescript-angular/platform-providers.ts +++ b/nativescript-angular/platform-providers.ts @@ -1,12 +1,11 @@ import { topmost, Frame } from 'ui/frame'; import { Page } from 'ui/page'; -import { OpaqueToken } from '@angular/core'; +import { OpaqueToken, Type } from '@angular/core'; import { device, Device } from "platform"; export const APP_ROOT_VIEW = new OpaqueToken('App Root View'); export const DEVICE = new OpaqueToken('platfrom device'); - -export const defaultPageProvider = { provide: Page, useFactory: getDefaultPage }; +export const PAGE_FACTORY = new OpaqueToken('page factory'); export function getDefaultPage(): Page { const frame = topmost(); @@ -16,7 +15,21 @@ export function getDefaultPage(): Page { return null; } } +export const defaultPageProvider = { provide: Page, useFactory: getDefaultPage }; export const defaultFrameProvider = { provide: Frame, useFactory: topmost }; export const defaultDeviceProvider = { provide: DEVICE, useValue: device }; + +export type PageFactory = (options: PageFactoryOptions) => Page; +export interface PageFactoryOptions { + isBootstrap?: boolean, + isLivesync?:boolean, + isModal?: boolean, + isNavigation?: boolean, + componentType?: any +} +export const defaultPageFactory: PageFactory = function (opts: PageFactoryOptions) { + return new Page(); +} +export const defaultPageFactoryProvider = { provide: PAGE_FACTORY, useValue: defaultPageFactory }; diff --git a/nativescript-angular/platform.ts b/nativescript-angular/platform.ts index 075e96dea..e3a889070 100644 --- a/nativescript-angular/platform.ts +++ b/nativescript-angular/platform.ts @@ -33,6 +33,8 @@ import { TextView } from 'ui/text-view'; import { NativeScriptElementSchemaRegistry } from './dom-adapter'; import { FileSystemResourceLoader } from './resource-loader'; +import { PAGE_FACTORY, PageFactory, defaultPageFactoryProvider } from './platform-providers'; + import * as nativescriptIntl from "nativescript-intl"; global.Intl = nativescriptIntl; @@ -60,6 +62,10 @@ export const NS_COMPILER_PROVIDERS = [ } ]; +const COMMON_PROVIDERS = [ + defaultPageFactoryProvider, +]; + export const onBeforeLivesync = new EventEmitter>(); export const onAfterLivesync = new EventEmitter>(); @@ -80,9 +86,9 @@ class NativeScriptPlatformRef extends PlatformRef { bootstrapModuleFactory(moduleFactory: NgModuleFactory): Promise> { this._bootstrapper = () => this.platform.bootstrapModuleFactory(moduleFactory); - + this.bootstrapApp(); - + return null; //Make the compiler happy } @@ -110,7 +116,8 @@ class NativeScriptPlatformRef extends PlatformRef { const mainPageEntry = this.createNavigationEntry( this._bootstrapper, compRef => onAfterLivesync.next(compRef), - error => onAfterLivesync.error(error) + error => onAfterLivesync.error(error), + true ); mainPageEntry.animated = false; mainPageEntry.clearHistory = true; @@ -140,10 +147,12 @@ class NativeScriptPlatformRef extends PlatformRef { return this.platform.destroyed; } - private createNavigationEntry(bootstrapAction: BootstrapperAction, resolve?: (comp: NgModuleRef) => void, reject?: (e: Error) => void, isReboot: boolean = false): NavigationEntry { + private createNavigationEntry(bootstrapAction: BootstrapperAction, resolve?: (comp: NgModuleRef) => void, reject?: (e: Error) => void, isLivesync: boolean = false, isReboot: boolean = false): NavigationEntry { + const pageFactory: PageFactory = this.platform.injector.get(PAGE_FACTORY); + const navEntry: NavigationEntry = { create: (): Page => { - let page = new Page(); + let page = pageFactory({ isBootstrap: true, isLivesync }); if (this.appOptions) { page.actionBarHidden = this.appOptions.startPageActionBarHidden; } @@ -199,7 +208,7 @@ class NativeScriptPlatformRef extends PlatformRef { // Dynamic platfrom const _platformNativeScriptDynamic: PlatformFactory = createPlatformFactory( - platformCoreDynamic, 'nativeScriptDynamic', NS_COMPILER_PROVIDERS); + platformCoreDynamic, 'nativeScriptDynamic', [...COMMON_PROVIDERS, ...NS_COMPILER_PROVIDERS]); export function platformNativeScriptDynamic(options?: AppOptions, extraProviders?: any[]): PlatformRef { //Return raw platform to advanced users only if explicitly requested @@ -212,7 +221,7 @@ export function platformNativeScriptDynamic(options?: AppOptions, extraProviders // "Static" platform const _platformNativeScript: PlatformFactory = createPlatformFactory( - platformCore, 'nativeScript'); + platformCore, 'nativeScript', [...COMMON_PROVIDERS]); export function platformNativeScript(options?: AppOptions, extraProviders?: any[]): PlatformRef { //Return raw platform to advanced users only if explicitly requested diff --git a/nativescript-angular/router/page-router-outlet.ts b/nativescript-angular/router/page-router-outlet.ts index 1122cf56a..0d8852b2c 100644 --- a/nativescript-angular/router/page-router-outlet.ts +++ b/nativescript-angular/router/page-router-outlet.ts @@ -3,17 +3,17 @@ import { ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef, Inject, ComponentFactoryResolver, Injector } from '@angular/core'; -import {isPresent} from "../lang-facade"; -import {RouterOutletMap, ActivatedRoute, PRIMARY_OUTLET} from '@angular/router'; -import {NSLocationStrategy} from "./ns-location-strategy"; -import {DEVICE} from "../platform-providers"; -import {Device} from "platform"; -import {routerLog} from "../trace"; -import {DetachedLoader} from "../common/detached-loader"; -import {ViewUtil} from "../view-util"; -import {Frame} from "ui/frame"; -import {Page, NavigatedData} from "ui/page"; -import {BehaviorSubject} from "rxjs"; +import { isPresent } from "../lang-facade"; +import { RouterOutletMap, ActivatedRoute, PRIMARY_OUTLET } from '@angular/router'; +import { NSLocationStrategy } from "./ns-location-strategy"; +import { DEVICE, PAGE_FACTORY, PageFactory } from "../platform-providers"; +import { Device } from "platform"; +import { routerLog } from "../trace"; +import { DetachedLoader } from "../common/detached-loader"; +import { ViewUtil } from "../view-util"; +import { Frame } from "ui/frame"; +import { Page, NavigatedData } from "ui/page"; +import { BehaviorSubject } from "rxjs"; interface CacheItem { componentRef: ComponentRef; @@ -95,7 +95,8 @@ export class PageRouterOutlet { private componentFactoryResolver: ComponentFactoryResolver, resolver: ComponentFactoryResolver, private frame: Frame, - @Inject(DEVICE) device: Device) { + @Inject(DEVICE) device: Device, + @Inject(PAGE_FACTORY) private pageFactory: PageFactory) { parentOutletMap.registerOutlet(name ? name : PRIMARY_OUTLET, this); @@ -141,10 +142,10 @@ export class PageRouterOutlet { * Called by the Router to instantiate a new component during the commit phase of a navigation. * This method in turn is responsible for calling the `routerOnActivate` hook of its child. */ - activate( - activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver, - loadedInjector: Injector, providers: ResolvedReflectiveProvider[], - outletMap: RouterOutletMap): void { + activate( + activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver, + loadedInjector: Injector, providers: ResolvedReflectiveProvider[], + outletMap: RouterOutletMap): void { this.outletMap = outletMap; this.currentActivatedRoute = activatedRoute; @@ -174,9 +175,9 @@ export class PageRouterOutlet { } else { log("PageRouterOutlet.activate() forward navigation - create detached loader in the loader container"); - const page = new Page(); + const page = this.pageFactory({ isNavigation: true, componentType: factory.componentType }); const pageResolvedProvider = ReflectiveInjector.resolve([ - {provide: Page, useValue: page} + { provide: Page, useValue: page } ]); const childInjector = ReflectiveInjector.fromResolvedProviders([...providers, ...pageResolvedProvider], this.containerRef.parentInjector); const loaderRef = this.containerRef.createComponent(this.detachedLoaderFactory, this.containerRef.length, childInjector, []); diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index c5959a064..b0b741e47 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -13,10 +13,13 @@ import { NativeScriptRouterModule } from "nativescript-angular/router"; import { NativeScriptFormsModule } from "nativescript-angular/forms"; import { NativeScriptHttpModule } from "nativescript-angular/http"; import { rendererTraceCategory, routerTraceCategory, listViewTraceCategory } from "nativescript-angular/trace"; +import { PAGE_FACTORY, PageFactory, PageFactoryOptions } from "nativescript-angular/platform-providers"; +import { Page } from "ui/page"; +import { Color } from "color"; import trace = require("trace"); // trace.setCategories(rendererTraceCategory); -trace.setCategories(routerTraceCategory); +// trace.setCategories(routerTraceCategory); // trace.setCategories(listViewTraceCategory); trace.enable(); @@ -62,7 +65,7 @@ import { AnimationStatesTest } from "./examples/animation/animation-states-test" ], providers: [] }) -class ExampleModule {} +class ExampleModule { } function makeExampleModule(componentType) { let imports: any[] = [ExampleModule]; @@ -93,25 +96,35 @@ function makeExampleModule(componentType) { providers: providers, exports: exports, }) - class ExampleModuleForComponent {} + class ExampleModuleForComponent { } return ExampleModuleForComponent; } -platformNativeScriptDynamic().bootstrapModule(makeExampleModule(RendererTest)); +const customPageFactoryProvider = { + provide: PAGE_FACTORY, + useValue: (opts: PageFactoryOptions) => { + const page = new Page(); + page.backgroundColor = opts.isModal ? new Color("lightblue") : new Color("lightgreen"); + return page; + } +}; + +// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(RendererTest)); +platformNativeScriptDynamic(undefined, [customPageFactoryProvider]).bootstrapModule(makeExampleModule(RendererTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(TabViewTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(Benchmark)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ListTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ListTestAsync)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ImageTest)); -//platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ModalTest)); +// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ModalTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(HttpTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PlatfromDirectivesTest)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ActionBarTest)); //new router //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(RouterOutletAppComponent)); -//platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PageRouterOutletAppComponent)); +// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PageRouterOutletAppComponent)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PageRouterOutletNestedAppComponent)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ClearHistoryAppComponent)); //platformNativeScriptDynamic().bootstrapModule(makeExampleModule(LoginAppComponent)); diff --git a/ng-sample/package.json b/ng-sample/package.json index b23ee5553..608ffa6a6 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -29,6 +29,7 @@ "@angular/core": "~2.1.1", "@angular/common": "~2.1.1", "@angular/compiler": "~2.1.1", + "@angular/forms": "~2.1.1", "@angular/http": "~2.1.1", "@angular/platform-browser": "~2.1.1", "@angular/platform-browser-dynamic": "~2.1.1",