From 52e15f4a0942c5490bb3ed807196d334fd6392c9 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Sat, 29 Apr 2017 17:01:30 -0700 Subject: [PATCH 01/17] feat(Modal): allow modal to be lazily loaded from a module on demand --- nativescript-angular/directives/dialogs.ts | 7 +- .../router/ns-module-factory-loader.ts | 19 ++++- ng-sample/package.json | 2 +- tests/app/lazy-loaded.module.ts | 27 ++++++- tests/app/main.ts | 2 +- tests/app/snippets/icon-font.component.html | 4 +- .../template-selector.component.html | 8 +-- tests/app/tests/list-view-tests.ts | 12 ++-- tests/app/tests/modal-dialog.ts | 72 +++++++++++++++++-- tests/app/tests/value-accessor-tests.ts | 2 +- 10 files changed, 130 insertions(+), 25 deletions(-) diff --git a/nativescript-angular/directives/dialogs.ts b/nativescript-angular/directives/dialogs.ts index 8953aa3d8..2fb756e95 100644 --- a/nativescript-angular/directives/dialogs.ts +++ b/nativescript-angular/directives/dialogs.ts @@ -1,5 +1,5 @@ import { - ReflectiveInjector, ComponentFactoryResolver, ViewContainerRef, + ReflectiveInjector, ComponentFactoryResolver, ViewContainerRef, NgModuleRef, Type, Injectable, ComponentRef, Directive } from "@angular/core"; import { Page } from "tns-core-modules/ui/page"; @@ -11,6 +11,7 @@ export interface ModalDialogOptions { context?: any; fullscreen?: boolean; viewContainerRef?: ViewContainerRef; + moduleRef?: NgModuleRef; } export class ModalDialogParams { @@ -30,7 +31,9 @@ export class ModalDialogService { const viewContainerRef = options.viewContainerRef; const parentPage: Page = viewContainerRef.injector.get(Page); - const resolver: ComponentFactoryResolver = viewContainerRef.injector.get( + // resolve from particular module (moduleRef) + // or from same module as parentPage (viewContainerRef) + const resolver: ComponentFactoryResolver = (options.moduleRef || viewContainerRef).injector.get( ComponentFactoryResolver); const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY); diff --git a/nativescript-angular/router/ns-module-factory-loader.ts b/nativescript-angular/router/ns-module-factory-loader.ts index c08cf5b93..b3dda3962 100644 --- a/nativescript-angular/router/ns-module-factory-loader.ts +++ b/nativescript-angular/router/ns-module-factory-loader.ts @@ -3,6 +3,7 @@ import { Compiler, NgModuleFactory, NgModuleFactoryLoader, + ModuleWithComponentFactories, SystemJsNgModuleLoader, } from "@angular/core"; @@ -26,13 +27,27 @@ export class NSModuleFactoryLoader implements NgModuleFactoryLoader { } } - private loadAndCompile(path: string): Promise> { + /** + * When needing the module with component factories + * Example: lazy loading on demand via user actions instead of routing + * Provides access to components in the lazy loaded module right away + * @param path module path + */ + public loadAndCompileComponents(path: string): Promise { + return this.loadAndCompile(path, true); + } + + private loadAndCompile(path: string, includeComponents?: boolean): Promise | ModuleWithComponentFactories> { let {modulePath, exportName} = splitPath(path); let loadedModule = global.require(modulePath)[exportName]; checkNotEmpty(loadedModule, modulePath, exportName); - return Promise.resolve(this.compiler.compileModuleAsync(loadedModule)); + if (includeComponents) { + return Promise.resolve(this.compiler.compileModuleAndAllComponentsAsync(loadedModule)); + } else { + return Promise.resolve(this.compiler.compileModuleAsync(loadedModule)); + } } } diff --git a/ng-sample/package.json b/ng-sample/package.json index 4b59f2282..ddce25ce9 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -61,4 +61,4 @@ "scripts": { "tslint": "tslint --project tsconfig.json --config tslint.json" } -} +} \ No newline at end of file diff --git a/tests/app/lazy-loaded.module.ts b/tests/app/lazy-loaded.module.ts index b3b60b401..13ac24300 100644 --- a/tests/app/lazy-loaded.module.ts +++ b/tests/app/lazy-loaded.module.ts @@ -1,19 +1,42 @@ -import { NgModule } from "@angular/core"; +import { Component, NgModule } from "@angular/core"; import { NativeScriptModule } from "nativescript-angular/nativescript.module"; import { NativeScriptRouterModule } from "nativescript-angular/router"; +import { ModalDialogParams } from "nativescript-angular/directives/dialogs"; +import { Page } from "ui/page"; +import { lazyLoadHooksLogProvider } from "./main"; import { SecondComponent } from "./second.component"; const routes = [ { path: ":id", component: SecondComponent }, ]; +@Component({ + selector: "modal-lazy-comp", + template: `` +}) +export class ModalLazyComponent { + constructor(public params: ModalDialogParams, private page: Page) { + page.on("shownModally", () => { + const result = this.params.context; + this.params.closeCallback(result); + }); + } +} + @NgModule({ - declarations: [SecondComponent], + declarations: [ + SecondComponent, + ModalLazyComponent + ], + entryComponents: [ModalLazyComponent], // when lazily loaded and opened via modal on demand imports: [ NativeScriptModule, NativeScriptRouterModule, NativeScriptRouterModule.forChild(routes) + ], + providers: [ + lazyLoadHooksLogProvider ] }) export class SecondModule { } diff --git a/tests/app/main.ts b/tests/app/main.ts index a35eaf68e..ce33b3f50 100644 --- a/tests/app/main.ts +++ b/tests/app/main.ts @@ -49,7 +49,7 @@ const singlePageHooksLogProvider = { provide: HOOKS_LOG, useValue: singlePageHoo const multiPageHooksLog = new BehaviorSubject([]); const multiPageHooksLogProvider = { provide: HOOKS_LOG, useValue: multiPageHooksLog }; const lazyLoadHooksLog = new BehaviorSubject([]); -const lazyLoadHooksLogProvider = { provide: HOOKS_LOG, useValue: lazyLoadHooksLog }; +export const lazyLoadHooksLogProvider = { provide: HOOKS_LOG, useValue: lazyLoadHooksLog }; @NgModule({ bootstrap: [ diff --git a/tests/app/snippets/icon-font.component.html b/tests/app/snippets/icon-font.component.html index ce804bf83..58933b150 100644 --- a/tests/app/snippets/icon-font.component.html +++ b/tests/app/snippets/icon-font.component.html @@ -1,12 +1,12 @@ - + diff --git a/tests/app/snippets/list-view/template-selector.component.html b/tests/app/snippets/list-view/template-selector.component.html index 065756798..75d346c1f 100644 --- a/tests/app/snippets/list-view/template-selector.component.html +++ b/tests/app/snippets/list-view/template-selector.component.html @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/tests/app/tests/list-view-tests.ts b/tests/app/tests/list-view-tests.ts index 6dfae0c74..20d4bf1d6 100644 --- a/tests/app/tests/list-view-tests.ts +++ b/tests/app/tests/list-view-tests.ts @@ -26,9 +26,9 @@ let testTemplates: { first: number, second: number }; template: ` - + ` @@ -60,12 +60,12 @@ export class ItemTemplateComponent { template: ` - - + ` diff --git a/tests/app/tests/modal-dialog.ts b/tests/app/tests/modal-dialog.ts index c14a13f36..2e08868c5 100644 --- a/tests/app/tests/modal-dialog.ts +++ b/tests/app/tests/modal-dialog.ts @@ -1,10 +1,17 @@ // make sure you import mocha-config before @angular/core import { assert } from "./test-config"; -import { TestApp } from "./test-app"; -import { Component, ViewContainerRef } from "@angular/core"; +import { TestApp, bootstrapTestApp } from "./test-app"; +import { Location, LocationStrategy } from "@angular/common"; +import { Component, ViewContainerRef, NgModuleFactoryLoader, ModuleWithComponentFactories, ComponentFactory, Compiler, Injector, Optional } from "@angular/core"; +import { NoPreloading, PreloadingStrategy, ROUTES, Route, Router, RouterModule, RouterOutletMap, Routes, UrlHandlingStrategy, UrlSerializer, provideRoutes, ɵROUTER_PROVIDERS as ROUTER_PROVIDERS, ɵflatten as flatten } from '@angular/router'; +import { BehaviorSubject } from "rxjs/BehaviorSubject"; import { Page } from "ui/page"; import { topmost } from "ui/frame"; import { ModalDialogParams, ModalDialogService } from "nativescript-angular/directives/dialogs"; +import { NSModuleFactoryLoader } from "nativescript-angular/router"; +import { HOOKS_LOG } from "../base.component"; +const lazyLoadHooksLog = new BehaviorSubject([]); +const lazyLoadHooksLogProvider = { provide: HOOKS_LOG, useValue: lazyLoadHooksLog }; import { device, platformNames } from "platform"; const CLOSE_WAIT = (device.os === platformNames.ios) ? 1000 : 0; @@ -33,16 +40,41 @@ export class FailComponent { } } +// TODO: this is done temporarily since the SecondModule is used to lazily load on demand here in the tests +// could create module specificly to test this +export function setupTestingRouter( + urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, + loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], + urlHandlingStrategy?: UrlHandlingStrategy) { + const router = new Router( + null !, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes)); + if (urlHandlingStrategy) { + router.urlHandlingStrategy = urlHandlingStrategy; + } + return router; +} + @Component({ selector: "sucess-comp", - providers: [ModalDialogService], + providers: [ + ModalDialogService, + { + provide: Router, useFactory: setupTestingRouter, + deps: [ + UrlSerializer, RouterOutletMap, Location, NgModuleFactoryLoader, Compiler, Injector, ROUTES, + [UrlHandlingStrategy, new Optional()] + ] + }, + lazyLoadHooksLogProvider, + { provide: NgModuleFactoryLoader, useClass: NSModuleFactoryLoader } + ], template: ` ` }) export class SuccessComponent { - constructor(public service: ModalDialogService, public vcRef: ViewContainerRef) { + constructor(public service: ModalDialogService, public vcRef: ViewContainerRef, public moduleLoader: NgModuleFactoryLoader) { } } @@ -109,4 +141,36 @@ describe("modal-dialog", () => { setTimeout(done, CLOSE_WAIT); // wait for the dialog to close in IOS }, err => done(err)); }); + + it("showModal provides module reference option when opening modal component which comes from lazy loaded module", (done) => { + const context = { property: "I was lazy loaded from another module on demand!" }; + let service, comp; + testApp.loadComponent(SuccessComponent) + .then((ref) => { + service = ref.instance.service; + comp = ref.instance; + return (comp.moduleLoader).loadAndCompileComponents("./lazy-loaded.module#SecondModule"); + }).then((mod: any) => { + const moduleRef = (>mod).ngModuleFactory.create(comp.vcRef.parentInjector); + // find component factory to ref the correct componentType + let lazyModalCmpFactory: ComponentFactory; + for (let cmp of mod.componentFactories) { + if (cmp.selector === "modal-lazy-comp") { // find by selector + lazyModalCmpFactory = cmp; + break; + } + } + + return service.showModal(lazyModalCmpFactory.componentType, { + moduleRef, + viewContainerRef: comp.vcRef, + context: context + }); + }) + .then((res) => { + assert.strictEqual(res, context); + setTimeout(done, CLOSE_WAIT); // wait for the dialog to close in IOS + }, err => done(err)); + + }); }); diff --git a/tests/app/tests/value-accessor-tests.ts b/tests/app/tests/value-accessor-tests.ts index 0f55fcba2..ac16c7eaa 100644 --- a/tests/app/tests/value-accessor-tests.ts +++ b/tests/app/tests/value-accessor-tests.ts @@ -102,7 +102,7 @@ describe("two-way binding via ng-model", () => { assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on empty"); accessor.writeValue("2010-03-17"); - assert.equal(formatDate(new Date(2010, 2, 17)), formatDate(accessor.view.date)); + assert.equal(formatDate(new Date(2010, 2, 16)), formatDate(accessor.view.date)); accessor.writeValue("a fortnight ago"); assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on parse error"); From 6a525c7e745a3c39b745c92c3aa42614aee7281d Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Sat, 29 Apr 2017 18:41:24 -0700 Subject: [PATCH 02/17] lint --- nativescript-angular/router/ns-module-factory-loader.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nativescript-angular/router/ns-module-factory-loader.ts b/nativescript-angular/router/ns-module-factory-loader.ts index b3dda3962..beca86f5b 100644 --- a/nativescript-angular/router/ns-module-factory-loader.ts +++ b/nativescript-angular/router/ns-module-factory-loader.ts @@ -37,7 +37,8 @@ export class NSModuleFactoryLoader implements NgModuleFactoryLoader { return this.loadAndCompile(path, true); } - private loadAndCompile(path: string, includeComponents?: boolean): Promise | ModuleWithComponentFactories> { + private loadAndCompile(path: string, includeComponents?: boolean): + Promise | ModuleWithComponentFactories> { let {modulePath, exportName} = splitPath(path); let loadedModule = global.require(modulePath)[exportName]; @@ -47,7 +48,7 @@ export class NSModuleFactoryLoader implements NgModuleFactoryLoader { return Promise.resolve(this.compiler.compileModuleAndAllComponentsAsync(loadedModule)); } else { return Promise.resolve(this.compiler.compileModuleAsync(loadedModule)); - } + } } } From 0b7ff46db76eb8558e1197820f343493718db8b8 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Tue, 2 May 2017 15:23:05 +0300 Subject: [PATCH 03/17] chore: update to Angular 4.1 and TypeScript 2.3 (#775) * chore(deps): update to Angular 4.1.0 * chore(lint): update tslint to ^5.1.0 and codelyzer to ^3.0.1 * refactor: fix lint errors * fix: make update-app-ng-deps work with peerDeps --- nativescript-angular/bin/update-app-ng-deps | 68 ++-- .../directives/list-view-comp.ts | 5 +- nativescript-angular/http.ts | 4 +- nativescript-angular/nativescript.module.ts | 2 +- nativescript-angular/package.json | 44 +- nativescript-angular/platform-common.ts | 2 +- nativescript-angular/tsconfig.json | 2 +- nativescript-angular/tslint.json | 1 - nativescript-angular/yarn.lock | 381 ++++++++++++++++++ ng-sample/package.json | 22 +- tests/package.json | 20 +- 11 files changed, 471 insertions(+), 80 deletions(-) create mode 100644 nativescript-angular/yarn.lock diff --git a/nativescript-angular/bin/update-app-ng-deps b/nativescript-angular/bin/update-app-ng-deps index 34b453a74..511bb76a8 100644 --- a/nativescript-angular/bin/update-app-ng-deps +++ b/nativescript-angular/bin/update-app-ng-deps @@ -1,33 +1,43 @@ #!/usr/bin/env node -var path = require("path"); -var fs = require("fs"); - -var binPath = __dirname; -var pluginPath = path.dirname(binPath); -var pluginPackageJsonPath = path.join(pluginPath, "package.json"); -var projectPath = path.dirname(path.dirname(pluginPath)); -var appPackageJsonPath = path.join(projectPath, "package.json"); - -var appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8")); -var pluginPackageJson = JSON.parse(fs.readFileSync(pluginPackageJsonPath, "utf8")); - -Object.keys(pluginPackageJson.dependencies).forEach(function(dependencyName) { - var version = pluginPackageJson.dependencies[dependencyName]; - if (dependencyName.startsWith("@angular") || dependencyName === "rxjs") { - appPackageJson.dependencies[dependencyName] = version; - console.log("Updated dependency '" + dependencyName + "' to version: " + version + "."); - } -}); - -Object.keys(pluginPackageJson.devDependencies).forEach(function(dependencyName) { - var version = pluginPackageJson.devDependencies[dependencyName]; - if (dependencyName.startsWith("@angular") || dependencyName === "zone.js") { - appPackageJson.devDependencies[dependencyName] = version; - console.log("Updated dev dependency '" + dependencyName + "' to version: " + version + "."); - } -}); - -fs.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2)); +const path = require("path"); +const fs = require("fs"); + +const binPath = __dirname; +const pluginPath = path.dirname(binPath); +const pluginPackageJsonPath = path.join(pluginPath, "package.json"); +const pluginPackageJson = JSON.parse(fs.readFileSync(pluginPackageJsonPath, "utf8")); +const pluginPeerDeps = pluginPackageJson.peerDependencies; + +const projectPath = path.dirname(path.dirname(pluginPath)); +const appPackageJsonPath = path.join(projectPath, "package.json"); +const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8")); + +const shouldUpdateDependency = name => name.startsWith("@angular") || + name === "rxjs" || + name === "zone.js"; + +let updatedDependencies = appPackageJson.dependencies; + +// set app dependencies to ones required from plugin (peer) +Object.keys(pluginPeerDeps) + .filter(shouldUpdateDependency) + .forEach(dependencyName => { + const version = pluginPackageJson.peerDependencies[dependencyName]; + updatedDependencies[dependencyName] = version; + console.log(`Updated dependency ${dependencyName} to version: ${version}.`); + }); + +// remove platform-browser-dynamic if present +const browserDynamicDependency = "@angular/platform-browser-dynamic"; +if (updatedDependencies.hasOwnProperty(browserDynamicDependency)) { + delete updatedDependencies[browserDynamicDependency]; + console.log(`Removed ${browserDynamicDependency}`); +} + +let updatedPackageJson = appPackageJson; +updatedPackageJson.dependencies = updatedDependencies; + +fs.writeFileSync(appPackageJsonPath, JSON.stringify(updatedPackageJson, null, 2)); console.log("\nAngular dependencies updated. Don't forget to run `npm install`."); diff --git a/nativescript-angular/directives/list-view-comp.ts b/nativescript-angular/directives/list-view-comp.ts index 93115b52f..781e80a1d 100644 --- a/nativescript-angular/directives/list-view-comp.ts +++ b/nativescript-angular/directives/list-view-comp.ts @@ -168,7 +168,7 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit { if (!viewRef) { listViewError("ViewReference not found for item " + index + ". View recycling is not working"); } - }; + } if (!viewRef) { listViewLog("onItemLoading: " + index + " - Creating view from template"); @@ -234,7 +234,8 @@ function getSingleViewRecursive(nodes: Array, nestLevel: number): View { export interface ComponentView { rootNodes: Array; destroy(): void; -}; +} + export type RootLocator = (nodes: Array, nestLevel: number) => View; export function getItemViewRoot(viewRef: ComponentView, rootLocator: RootLocator = getSingleViewRecursive): View { diff --git a/nativescript-angular/http.ts b/nativescript-angular/http.ts index 2780a6fb3..5f6583a02 100644 --- a/nativescript-angular/http.ts +++ b/nativescript-angular/http.ts @@ -11,11 +11,11 @@ export { NSHttp } from "./http/ns-http"; export function nsHttpFactory(backend, options, nsFileSystem) { return new NSHttp(backend, options, nsFileSystem); -}; +} export function nsXSRFStrategyFactory() { return new NSXSRFStrategy(); -}; +} @NgModule({ providers: [ diff --git a/nativescript-angular/nativescript.module.ts b/nativescript-angular/nativescript.module.ts index dd84f6366..521e926ee 100644 --- a/nativescript-angular/nativescript.module.ts +++ b/nativescript-angular/nativescript.module.ts @@ -26,7 +26,7 @@ import { NS_DIRECTIVES } from "./directives"; export function errorHandlerFactory() { return new ErrorHandler(true); -}; +} @NgModule({ declarations: [ diff --git a/nativescript-angular/package.json b/nativescript-angular/package.json index 00cbe67c0..8f8abf671 100644 --- a/nativescript-angular/package.json +++ b/nativescript-angular/package.json @@ -29,7 +29,7 @@ "url": "https://github.com/NativeScript/nativescript-angular.git" }, "scripts": { - "tslint": "tslint --project tsconfig.json --config tslint.json", + "tslint": "tslint --project tsconfig.json --config tslint.json --type-check", "postinstall": "node postinstall.js", "tsc": "tsc -p tsconfig.json", "ngc": "ngc -p tsconfig.json", @@ -43,32 +43,32 @@ "reflect-metadata": "^0.1.8" }, "peerDependencies": { - "@angular/core": "~4.0.0", - "@angular/common": "~4.0.0", - "@angular/compiler": "~4.0.0", - "@angular/platform-browser": "~4.0.0", - "@angular/router": "~4.0.0", - "@angular/forms": "~4.0.0", - "@angular/http": "~4.0.0", - "tns-core-modules": "^3.0.0 || ^3.0.0-rc.1", + "@angular/common": "~4.0.0 || ~4.1.0", + "@angular/compiler": "~4.0.0 || ~4.1.0", + "@angular/core": "~4.0.0 || ~4.1.0", + "@angular/forms": "~4.0.0 || ~4.1.0", + "@angular/http": "~4.0.0 || ~4.1.0", + "@angular/platform-browser": "~4.0.0 || ~4.1.0", + "@angular/router": "~4.0.0 || ~4.1.0", "rxjs": "^5.0.1", + "tns-core-modules": "^3.0.0 || ^3.0.0-rc.1", "zone.js": "^0.8.4" }, "devDependencies": { - "@angular/core": "~4.0.0", - "@angular/common": "~4.0.0", - "@angular/compiler": "~4.0.0", - "@angular/compiler-cli": "~4.0.0", - "@angular/platform-browser": "~4.0.0", - "@angular/animations": "~4.0.0", - "@angular/router": "~4.0.0", - "@angular/forms": "~4.0.0", - "@angular/http": "~4.0.0", - "codelyzer": "~3.0.0-beta.4", - "tns-core-modules": "internal-preview", - "tslint": "~4.5.0", - "typescript": "~2.2.1", + "@angular/animations": "~4.0.0 || ~4.1.0", + "@angular/common": "~4.0.0 || ~4.1.0", + "@angular/compiler": "~4.0.0 || ~4.1.0", + "@angular/compiler-cli": "~4.0.0 || ~4.1.0", + "@angular/core": "~4.0.0 || ~4.1.0", + "@angular/forms": "~4.0.0 || ~4.1.0", + "@angular/http": "~4.0.0 || ~4.1.0", + "@angular/platform-browser": "~4.0.0 || ~4.1.0", + "@angular/router": "~4.0.0 || ~4.1.0", + "codelyzer": "^3.0.1", "rxjs": "^5.0.1", + "tns-core-modules": "internal-preview", + "tslint": "^5.1.0", + "typescript": "^2.3.2", "zone.js": "^0.8.4" } } diff --git a/nativescript-angular/platform-common.ts b/nativescript-angular/platform-common.ts index a8381f5c5..bd2373347 100644 --- a/nativescript-angular/platform-common.ts +++ b/nativescript-angular/platform-common.ts @@ -129,7 +129,7 @@ export class NativeScriptPlatformRef extends PlatformRef { get injector(): Injector { return this.platform.injector; - }; + } destroy(): void { this.platform.destroy(); diff --git a/nativescript-angular/tsconfig.json b/nativescript-angular/tsconfig.json index 17fd0ba01..641cfd5e2 100644 --- a/nativescript-angular/tsconfig.json +++ b/nativescript-angular/tsconfig.json @@ -31,6 +31,6 @@ "genDir": ".", "skipMetadataEmit": false, "skipTemplateCodegen": true, - "debug": true + "strictMetadataEmit": true } } diff --git a/nativescript-angular/tslint.json b/nativescript-angular/tslint.json index 4db4b9408..faae1470c 100644 --- a/nativescript-angular/tslint.json +++ b/nativescript-angular/tslint.json @@ -62,7 +62,6 @@ "no-string-literal": false, "no-switch-case-fall-through": true, "no-unused-expression": true, - "no-use-before-declare": true, "no-var-keyword": true, "radix": false, "switch-default": true, diff --git a/nativescript-angular/yarn.lock b/nativescript-angular/yarn.lock new file mode 100644 index 000000000..2ade79c72 --- /dev/null +++ b/nativescript-angular/yarn.lock @@ -0,0 +1,381 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@angular/animations@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.1.0.tgz#97b642aee01b5406e03ec65e499342ba91e2dd38" + +"@angular/common@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.1.0.tgz#4370f569e51ddd99963b7f4aa58c1a5dcc5fea52" + +"@angular/compiler-cli@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.1.0.tgz#727aaada8bfd94285e9818995925048f7fdf1200" + dependencies: + "@angular/tsc-wrapped" "4.1.0" + minimist "^1.2.0" + reflect-metadata "^0.1.2" + +"@angular/compiler@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.1.0.tgz#be1ade5b6aec81f03c29d52bcb95925a28900dcb" + +"@angular/core@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.1.0.tgz#72ec173316879571880c9c483ed6dfc0caab94b0" + +"@angular/forms@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.1.0.tgz#8eae2a45c4ba064b377f9280e59c012b5dac6b80" + +"@angular/http@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.1.0.tgz#7ba0c4d044dee964021b7cf19cb146a2c31577a5" + +"@angular/platform-browser@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.1.0.tgz#b981386be1a36f2af7f0679447fd97b7267b25de" + +"@angular/router@~4.0.0 || ~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.1.0.tgz#dd3563662f95ca3aa3dd9ff13c6ed4bea1d90b06" + +"@angular/tsc-wrapped@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.1.0.tgz#07cbd61d91adde4c2daf9a41605152952b8832b3" + dependencies: + tsickle "^0.21.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +app-root-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46" + +babel-code-frame@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +brace-expansion@^1.0.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +chalk@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +codelyzer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-3.0.1.tgz#ba66b7b2aa564fe9f45d6004b4003ad2cf116828" + dependencies: + app-root-path "^2.0.1" + css-selector-tokenizer "^0.7.0" + cssauron "^1.4.0" + semver-dsl "^1.0.1" + source-map "^0.5.6" + sprintf-js "^1.0.3" + +colors@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +css-selector-tokenizer@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" + dependencies: + cssesc "^0.1.0" + fastparse "^1.1.1" + regexpu-core "^1.0.0" + +cssauron@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8" + dependencies: + through X.X.X + +cssesc@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" + +diff@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +fastparse@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" + +findup-sync@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" + dependencies: + glob "~5.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +glob@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~5.0.0: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +js-tokens@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +"minimatch@2 || 3", minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +nativescript-intl@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/nativescript-intl/-/nativescript-intl-3.0.0.tgz#82ee9be7d377172b3c4295734723037628e186a7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optimist@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +reflect-metadata@^0.1.2, reflect-metadata@^0.1.8: + version "0.1.10" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a" + +regenerate@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" + +regexpu-core@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +resolve@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" + dependencies: + path-parse "^1.0.5" + +rxjs@^5.0.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.3.0.tgz#d88ccbdd46af290cbdb97d5d8055e52453fabe2d" + dependencies: + symbol-observable "^1.0.1" + +semver-dsl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/semver-dsl/-/semver-dsl-1.0.1.tgz#d3678de5555e8a61f629eed025366ae5f27340a0" + dependencies: + semver "^5.3.0" + +semver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +source-map-support@^0.4.2: + version "0.4.15" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" + dependencies: + source-map "^0.5.6" + +source-map@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +sprintf-js@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +symbol-observable@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" + +through@X.X.X: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tns-core-modules-widgets@internal-preview: + version "3.1.0-2017-04-28-266" + resolved "https://registry.yarnpkg.com/tns-core-modules-widgets/-/tns-core-modules-widgets-3.1.0-2017-04-28-266.tgz#56d82a9952604e064b76bbd232d56cad9a13337a" + +tns-core-modules@internal-preview: + version "3.1.0-2017-04-26-6412" + resolved "https://registry.yarnpkg.com/tns-core-modules/-/tns-core-modules-3.1.0-2017-04-26-6412.tgz#ae7717292d511e3e6fcac14330d0b0adc18e905d" + dependencies: + tns-core-modules-widgets internal-preview + +tsickle@^0.21.0: + version "0.21.6" + resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.21.6.tgz#53b01b979c5c13fdb13afb3fb958177e5991588d" + dependencies: + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map "^0.5.6" + source-map-support "^0.4.2" + +tslint@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.1.0.tgz#51a47baeeb58956fcd617bd2cf00e2ef0eea2ed9" + dependencies: + babel-code-frame "^6.22.0" + colors "^1.1.2" + diff "^3.2.0" + findup-sync "~0.3.0" + glob "^7.1.1" + optimist "~0.6.0" + resolve "^1.3.2" + semver "^5.3.0" + tsutils "^1.4.0" + +tsutils@^1.4.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.8.0.tgz#bf8118ed8e80cd5c9fc7d75728c7963d44ed2f52" + +typescript@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +zone.js@^0.8.4: + version "0.8.9" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.9.tgz#34aaa9a3ec6d0e4acebd1b761adafa590473638b" diff --git a/ng-sample/package.json b/ng-sample/package.json index ddce25ce9..b0b169a3a 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -32,18 +32,18 @@ }, "homepage": "https://github.com/NativeScript/template-hello-world", "dependencies": { - "@angular/animations": "~4.0.0", - "@angular/common": "~4.0.0", - "@angular/compiler": "~4.0.0", - "@angular/core": "~4.0.0", - "@angular/forms": "~4.0.0", - "@angular/http": "~4.0.0", - "@angular/platform-browser": "~4.0.0", - "@angular/platform-browser-dynamic": "~4.0.0", - "@angular/router": "~4.0.0", + "@angular/animations": "~4.1.0", + "@angular/common": "~4.1.0", + "@angular/compiler": "~4.1.0", + "@angular/core": "~4.1.0", + "@angular/forms": "~4.1.0", + "@angular/http": "~4.1.0", + "@angular/platform-browser": "~4.1.0", + "@angular/platform-browser-dynamic": "~4.1.0", + "@angular/router": "~4.1.0", "nativescript-angular": "file:../nativescript-angular", - "rxjs": "~5.2.0", - "tns-core-modules": "internal-preview", + "rxjs": "^5.3.0", + "tns-core-modules": "^3.0.0 || ^3.0.0-rc.1", "zone.js": "~0.8.2" }, "devDependencies": { diff --git a/tests/package.json b/tests/package.json index 7b579e011..fb8cbbd5c 100644 --- a/tests/package.json +++ b/tests/package.json @@ -26,15 +26,15 @@ ], "homepage": "http://nativescript.org", "dependencies": { - "@angular/animations": "~4.0.0", - "@angular/common": "~4.0.0", - "@angular/compiler": "~4.0.0", - "@angular/core": "~4.0.0", - "@angular/forms": "~4.0.0", - "@angular/http": "~4.0.0", - "@angular/platform-browser": "~4.0.0", - "@angular/platform-browser-dynamic": "~4.0.0", - "@angular/router": "~4.0.0", + "@angular/animations": "~4.1.0", + "@angular/common": "~4.1.0", + "@angular/compiler": "~4.1.0", + "@angular/core": "~4.1.0", + "@angular/forms": "~4.1.0", + "@angular/http": "~4.1.0", + "@angular/platform-browser": "~4.1.0", + "@angular/platform-browser-dynamic": "~4.1.0", + "@angular/router": "~4.1.0", "nativescript-angular": "../nativescript-angular", "nativescript-unit-test-runner": "^0.3.4", "rxjs": "^5.2.0", @@ -57,7 +57,7 @@ "lazy": "1.0.11", "mocha": "^2.4.5", "nativescript-dev-appium": "0.0.14", - "nativescript-dev-typescript": "^0.3.1", + "nativescript-dev-typescript": "^0.4.0", "socket.io": "1.4.8", "socket.io-client": "1.4.8", "tslint": "^4.5.1", From b652d105d04e1c098f9503792e4f1f202d518bb4 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Wed, 3 May 2017 18:41:30 +0300 Subject: [PATCH 04/17] fix: update-app-ng-deps works for all @angular packages (#779) This should update all angular packages that the project depends on, such as @angular/animations and @angular/compiler-cli. --- nativescript-angular/bin/update-app-ng-deps | 61 +++++++++++++-------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/nativescript-angular/bin/update-app-ng-deps b/nativescript-angular/bin/update-app-ng-deps index 511bb76a8..7676e3313 100644 --- a/nativescript-angular/bin/update-app-ng-deps +++ b/nativescript-angular/bin/update-app-ng-deps @@ -3,41 +3,56 @@ const path = require("path"); const fs = require("fs"); +const browserDynamicDependency = "@angular/platform-browser-dynamic"; const binPath = __dirname; const pluginPath = path.dirname(binPath); const pluginPackageJsonPath = path.join(pluginPath, "package.json"); const pluginPackageJson = JSON.parse(fs.readFileSync(pluginPackageJsonPath, "utf8")); -const pluginPeerDeps = pluginPackageJson.peerDependencies; - -const projectPath = path.dirname(path.dirname(pluginPath)); -const appPackageJsonPath = path.join(projectPath, "package.json"); -const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8")); -const shouldUpdateDependency = name => name.startsWith("@angular") || +const isNgDependency = name => name.startsWith("@angular") || name === "rxjs" || name === "zone.js"; -let updatedDependencies = appPackageJson.dependencies; +function updateDeps(deps, newDeps) { + // set app dependencies to ones required from plugin + Object.keys(newDeps) + .filter(isNgDependency) + .filter(dependencyName => deps.hasOwnProperty(dependencyName)) + .map(dependencyName => ({ + dependencyName, + version: pluginPackageJson.peerDependencies[dependencyName] + })) + .filter(({ dependencyName, version }) => deps[dependencyName] !== version) + .forEach(({ dependencyName, version }) => { + deps[dependencyName] = version; + console.log(`Updated dependency ${dependencyName} to version: ${version}.`); + }); + + // remove platform-browser-dynamic if present + if (deps.hasOwnProperty(browserDynamicDependency)) { + delete deps[browserDynamicDependency]; + console.log(`Removed ${browserDynamicDependency}`); + } + + + return deps; +} -// set app dependencies to ones required from plugin (peer) -Object.keys(pluginPeerDeps) - .filter(shouldUpdateDependency) - .forEach(dependencyName => { - const version = pluginPackageJson.peerDependencies[dependencyName]; - updatedDependencies[dependencyName] = version; - console.log(`Updated dependency ${dependencyName} to version: ${version}.`); +let pluginDeps = pluginPackageJson.peerDependencies; +Object.keys(pluginPackageJson.devDependencies) + .filter(isNgDependency) + .filter(depName => !pluginDeps.hasOwnProperty(depName)) + .forEach(depName => { + pluginDeps[depName] = pluginPackageJson.devDependencies[depName]; }); -// remove platform-browser-dynamic if present -const browserDynamicDependency = "@angular/platform-browser-dynamic"; -if (updatedDependencies.hasOwnProperty(browserDynamicDependency)) { - delete updatedDependencies[browserDynamicDependency]; - console.log(`Removed ${browserDynamicDependency}`); -} +const projectPath = path.dirname(path.dirname(pluginPath)); +const appPackageJsonPath = path.join(projectPath, "package.json"); +const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8")); -let updatedPackageJson = appPackageJson; -updatedPackageJson.dependencies = updatedDependencies; +appPackageJson.dependencies = updateDeps(appPackageJson.dependencies, pluginDeps); +appPackageJson.devDependencies = updateDeps(appPackageJson.devDependencies, pluginDeps); -fs.writeFileSync(appPackageJsonPath, JSON.stringify(updatedPackageJson, null, 2)); +fs.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2)); console.log("\nAngular dependencies updated. Don't forget to run `npm install`."); From dac192cc968ec5c927262e2dc5987bafa5c13e53 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Wed, 3 May 2017 18:41:38 +0300 Subject: [PATCH 05/17] docs: update 3.0.0 changelog (#780) --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f38b30ab..aa037c81d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,57 @@ + +# [3.0.0](https://github.com/NativeScript/nativescript-angular/compare/v1.5.2..v3.0.0) (2017-05-03) + + +### Bug Fixes + +* **action-bar:** Don't remove action items twice. ([b96b61f](https://github.com/NativeScript/nativescript-angular/commit/b96b61f)) +* **animations:** add onDestroy method to NativeScriptAnimationPlayer ([ec07ec3](https://github.com/NativeScript/nativescript-angular/commit/ec07ec3)) +* **animations:** set nodeType 'element' to newly created views ([#720](https://github.com/NativeScript/nativescript-angular/issues/720)) ([8af20ad](https://github.com/NativeScript/nativescript-angular/commit/8af20ad)) +* **gitignore:** Add editor files into gitignore ([9beea98](https://github.com/NativeScript/nativescript-angular/commit/9beea98)) +* **init:** Bootstrap Angular on page "navigatingTo" event. ([85b9d01](https://github.com/NativeScript/nativescript-angular/commit/85b9d01)) +* **list-view:** Destroy item views on unload ([71301aa](https://github.com/NativeScript/nativescript-angular/commit/71301aa)) +* **list-view:** Do not access destroyed items' ng views. ([c6f7549](https://github.com/NativeScript/nativescript-angular/commit/c6f7549)) +* **list-view-comp:** IterableDiffer is now parameterized on ([f692c5f](https://github.com/NativeScript/nativescript-angular/commit/f692c5f)) +* **ns-http:** make defaultOptions of type RequestOptions ([073c95d](https://github.com/NativeScript/nativescript-angular/commit/073c95d)) +* **action bar:** attach #comment nodes with _addView ([#729](https://github.com/NativeScript/nativescript-angular/issues/729)) ([0490605](https://github.com/NativeScript/nativescript-angular/commit/0490605)), closes [#725](https://github.com/NativeScript/nativescript-angular/issues/725) +* **ns-router-link:** navigate with urlTree ([#728](https://github.com/NativeScript/nativescript-angular/issues/728)) ([3c6f5ab](https://github.com/NativeScript/nativescript-angular/commit/3c6f5ab)), closes [#724](https://github.com/NativeScript/nativescript-angular/issues/724) +* use providers' map for injectors in page-router-outlet ([#744](https://github.com/NativeScript/nativescript-angular/issues/744)) ([07fe66c](https://github.com/NativeScript/nativescript-angular/commit/07fe66c)), closes [#741](https://github.com/NativeScript/nativescript-angular/issues/741) + + +### Code Refactoring + +* stop exporting NativeScriptModule from platform ([#701](https://github.com/NativeScript/nativescript-angular/issues/701)) ([0bd2ba5](https://github.com/NativeScript/nativescript-angular/commit/0bd2ba5)) + + +### Features + +* **animations:** introduce NativeScriptAnimationsModule ([#704](https://github.com/NativeScript/nativescript-angular/issues/704)) ([f9ad6a5](https://github.com/NativeScript/nativescript-angular/commit/f9ad6a5)) +* **renderer:** use EmulatedRenderer to scope component styles ([70603c4](https://github.com/NativeScript/nativescript-angular/commit/70603c4)) +* **renderer:** implement createComment and createText methods using ([0f128ad](https://github.com/NativeScript/nativescript-angular/commit/0f128ad)) +* **renderer:** support namespaced attributes ([#719](https://github.com/NativeScript/nativescript-angular/issues/719)) ([9b5b413](https://github.com/NativeScript/nativescript-angular/commit/9b5b413)) + + +### BREAKING CHANGES + +* **animations:** To use animations, you need to import the +NativeScriptAnimationsModule from "nativescript-angular/animations" in +your root NgModule. +* User applications cannot import NativeScriptModule from +"nativescript-angular/platform" anymore. +Migration: +Before: +``` +import { NativeScriptModule } from "nativescript-angular/platform"; +``` +After +``` +import { NativeScriptModule } from +"nativescript-angular/nativescript.module"; +``` + + + + ## [1.5.2](https://github.com/NativeScript/nativescript-angular/compare/v1.5.1...v1.5.2) (2017-04-18) From 1d826719c396c07dbd9f0671afcf9376571f111e Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 4 May 2017 17:30:30 +0300 Subject: [PATCH 06/17] Update npm tag (#782) --- .travis.yml | 2 +- nativescript-angular/package.json | 4 ++-- ng-sample/package.json | 2 +- tests/package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 903364dbc..3e947ce77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ before_deploy: - npm install -g nativescript --ignore-scripts - tns usage-reporting disable - tns error-reporting disable -- node ../build/travis-scripts/add-publishConfig.js internal-preview $PACKAGE_VERSION +- node ../build/travis-scripts/add-publishConfig.js next $PACKAGE_VERSION deploy: provider: npm email: nativescript@telerik.com diff --git a/nativescript-angular/package.json b/nativescript-angular/package.json index 8f8abf671..f08150dcb 100644 --- a/nativescript-angular/package.json +++ b/nativescript-angular/package.json @@ -51,7 +51,7 @@ "@angular/platform-browser": "~4.0.0 || ~4.1.0", "@angular/router": "~4.0.0 || ~4.1.0", "rxjs": "^5.0.1", - "tns-core-modules": "^3.0.0 || ^3.0.0-rc.1", + "tns-core-modules": "^3.0.0", "zone.js": "^0.8.4" }, "devDependencies": { @@ -66,7 +66,7 @@ "@angular/router": "~4.0.0 || ~4.1.0", "codelyzer": "^3.0.1", "rxjs": "^5.0.1", - "tns-core-modules": "internal-preview", + "tns-core-modules": "next", "tslint": "^5.1.0", "typescript": "^2.3.2", "zone.js": "^0.8.4" diff --git a/ng-sample/package.json b/ng-sample/package.json index b0b169a3a..5340da35d 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -43,7 +43,7 @@ "@angular/router": "~4.1.0", "nativescript-angular": "file:../nativescript-angular", "rxjs": "^5.3.0", - "tns-core-modules": "^3.0.0 || ^3.0.0-rc.1", + "tns-core-modules": "next", "zone.js": "~0.8.2" }, "devDependencies": { diff --git a/tests/package.json b/tests/package.json index fb8cbbd5c..0b894576e 100644 --- a/tests/package.json +++ b/tests/package.json @@ -38,7 +38,7 @@ "nativescript-angular": "../nativescript-angular", "nativescript-unit-test-runner": "^0.3.4", "rxjs": "^5.2.0", - "tns-core-modules": "internal-preview", + "tns-core-modules": "next", "zone.js": "^0.8.2" }, "devDependencies": { From 10f61647ffaf281c6fe1f023a1231db805678e00 Mon Sep 17 00:00:00 2001 From: SvetoslavTsenov Date: Mon, 8 May 2017 18:29:52 +0300 Subject: [PATCH 07/17] Update .travis.yml Update emulator api level to 23 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3e947ce77..e9ad43870 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ android: - build-tools-23.0.1 - android-23 - extra-android-m2repository - - sys-img-armeabi-v7a-android-19 + - sys-img-armeabi-v7a-android-23 before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock cache: @@ -40,7 +40,7 @@ script: - - tns build android - android-wait-for-emulator -- npm run run-appium-android +- npm run run-appium-android-23 before_deploy: - cd ../nativescript-angular - npm install -g nativescript --ignore-scripts From eb4b6cfbf5da9740953e50facb2ea4b3d27f44c3 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Tue, 9 May 2017 16:46:18 +0300 Subject: [PATCH 08/17] fix(renderer): set templateParent to comment and text nodes (#785) * fix(renderer): set templateParent for newly create DetachedText nodes DetachedText is not inserted in the UI components tree, so we need to add it's parent manually. * fix(renderer): respect templateParent in parentNode() if one is set fixes #777, fixes #787 * test: add unit test for NgIfElse and NgIfThenElse * chore: target 'next' tag of tns-core-modules * fix(renderer): stop attaching comments to visual tree * refactor(renderer): create DetachedElements instead for comments and text nodes * refactor: move NgView, NgElement and similar to separate module --- .../animations/animation-driver.ts | 2 +- .../animations/animation-engine.ts | 2 +- .../animations/animation-player.ts | 2 +- nativescript-angular/animations/dom-utils.ts | 2 +- nativescript-angular/directives/action-bar.ts | 10 +- .../directives/list-view-comp.ts | 58 +++++---- nativescript-angular/directives/tab-view.ts | 18 ++- nativescript-angular/element-registry.ts | 39 +----- nativescript-angular/element-types.ts | 32 +++++ nativescript-angular/index.ts | 11 +- nativescript-angular/renderer.ts | 24 ++-- nativescript-angular/view-util.ts | 55 ++++---- ng-sample/app/app.ts | 4 +- ng-sample/app/examples/renderer-test.html | 56 ++++---- ng-sample/package.json | 7 +- tests/app/tests/property-sets.ts | 2 +- tests/app/tests/renderer-tests.ts | 120 ++++++++++++++++-- 17 files changed, 280 insertions(+), 164 deletions(-) create mode 100644 nativescript-angular/element-types.ts diff --git a/nativescript-angular/animations/animation-driver.ts b/nativescript-angular/animations/animation-driver.ts index d1dd2b032..a2e6de0ca 100644 --- a/nativescript-angular/animations/animation-driver.ts +++ b/nativescript-angular/animations/animation-driver.ts @@ -1,6 +1,6 @@ import { AnimationPlayer } from "@angular/animations"; -import { NgView } from "../element-registry"; +import { NgView } from "../element-types"; import { NativeScriptAnimationPlayer } from "./animation-player"; import { Keyframe } from "./utils"; diff --git a/nativescript-angular/animations/animation-engine.ts b/nativescript-angular/animations/animation-engine.ts index 0dcbd51ff..527ae603c 100644 --- a/nativescript-angular/animations/animation-engine.ts +++ b/nativescript-angular/animations/animation-engine.ts @@ -1,7 +1,7 @@ import { ɵDomAnimationEngine as DomAnimationEngine } from "@angular/animations/browser"; import { AnimationEvent, AnimationPlayer } from "@angular/animations"; -import { NgView } from "../element-registry"; +import { NgView } from "../element-types"; import { copyArray, cssClasses, diff --git a/nativescript-angular/animations/animation-player.ts b/nativescript-angular/animations/animation-player.ts index fcc60d8f1..d4f648c15 100644 --- a/nativescript-angular/animations/animation-player.ts +++ b/nativescript-angular/animations/animation-player.ts @@ -4,7 +4,7 @@ import { KeyframeAnimationInfo, } from "tns-core-modules/ui/animation/keyframe-animation"; -import { NgView } from "../element-registry"; +import { NgView } from "../element-types"; import { Keyframe, getAnimationCurve, parseAnimationKeyframe } from "./utils"; export class NativeScriptAnimationPlayer implements AnimationPlayer { diff --git a/nativescript-angular/animations/dom-utils.ts b/nativescript-angular/animations/dom-utils.ts index 00584f70e..c6a54039b 100644 --- a/nativescript-angular/animations/dom-utils.ts +++ b/nativescript-angular/animations/dom-utils.ts @@ -7,7 +7,7 @@ import { } from "@angular/animations"; import { unsetValue } from "tns-core-modules/ui/core/view"; -import { NgView } from "../element-registry"; +import { NgView } from "../element-types"; // overriden to use the default 'unsetValue' // instead of empty string '' diff --git a/nativescript-angular/directives/action-bar.ts b/nativescript-angular/directives/action-bar.ts index bb9076a4b..876befa45 100644 --- a/nativescript-angular/directives/action-bar.ts +++ b/nativescript-angular/directives/action-bar.ts @@ -1,13 +1,15 @@ import { Directive, Component, ElementRef, Optional, OnDestroy } from "@angular/core"; import { ActionItem, ActionBar, NavigationButton } from "tns-core-modules/ui/action-bar"; -import { isBlank } from "../lang-facade"; import { Page } from "tns-core-modules/ui/page"; import { View } from "tns-core-modules/ui/core/view"; -import { registerElement, ViewClassMeta, NgView } from "../element-registry"; + +import { isBlank } from "../lang-facade"; +import { registerElement } from "../element-registry"; +import { ViewClassMeta, NgView } from "../element-types"; const actionBarMeta: ViewClassMeta = { skipAddToDom: true, - insertChild: (parent: NgView, child: NgView, atIndex: number) => { + insertChild: (parent: NgView, child: NgView) => { const bar = (parent); const childView = child; @@ -17,8 +19,6 @@ const actionBarMeta: ViewClassMeta = { } else if (child instanceof ActionItem) { bar.actionItems.addItem(childView); childView.parent = bar; - } else if (child.nodeName === "#comment") { - bar._addView(childView, atIndex); } else if (child instanceof View) { bar.titleView = childView; } diff --git a/nativescript-angular/directives/list-view-comp.ts b/nativescript-angular/directives/list-view-comp.ts index 781e80a1d..ccfcac8f0 100644 --- a/nativescript-angular/directives/list-view-comp.ts +++ b/nativescript-angular/directives/list-view-comp.ts @@ -1,29 +1,31 @@ import { + AfterContentInit, + ChangeDetectionStrategy, + ChangeDetectorRef, Component, + ContentChild, Directive, - Input, DoCheck, - OnDestroy, - AfterContentInit, ElementRef, - ViewContainerRef, - TemplateRef, - ContentChild, EmbeddedViewRef, - IterableDiffers, - IterableDiffer, - ChangeDetectorRef, EventEmitter, - ViewChild, - Output, Host, - ChangeDetectionStrategy + Input, + IterableDiffer, + IterableDiffers, + OnDestroy, + Output, + TemplateRef, + ViewChild, + ViewContainerRef, } from "@angular/core"; -import { isListLikeIterable } from "../collection-facade"; import { ListView, ItemEventData } from "tns-core-modules/ui/list-view"; import { View, KeyedTemplate } from "tns-core-modules/ui/core/view"; import { ObservableArray } from "tns-core-modules/data/observable-array"; import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; + +import { CommentNode } from "../element-types"; +import { isListLikeIterable } from "../collection-facade"; import { listViewLog, listViewError } from "../trace"; const NG_VIEW = "_ngViewRef"; @@ -212,23 +214,27 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit { } function getSingleViewRecursive(nodes: Array, nestLevel: number): View { - const actualNodes = nodes.filter((n) => !!n && n.nodeName !== "#text"); + const actualNodes = nodes.filter(node => !(node instanceof CommentNode)); if (actualNodes.length === 0) { - throw new Error("No suitable views found in list template! Nesting level: " + nestLevel); + throw new Error(`No suitable views found in list template! ` + + `Nesting level: ${nestLevel}`); } else if (actualNodes.length > 1) { - throw new Error("More than one view found in list template! Nesting level: " + nestLevel); - } else { - if (actualNodes[0]) { - let parentLayout = actualNodes[0].parent; - if (parentLayout instanceof LayoutBase) { - parentLayout.removeChild(actualNodes[0]); - } - return actualNodes[0]; - } else { - return getSingleViewRecursive(actualNodes[0].children, nestLevel + 1); - } + throw new Error(`More than one view found in list template!` + + `Nesting level: ${nestLevel}`); + } + + const rootLayout = actualNodes[0]; + if (!rootLayout) { + return getSingleViewRecursive(rootLayout.children, nestLevel + 1); + } + + let parentLayout = rootLayout.parent; + if (parentLayout instanceof LayoutBase) { + parentLayout.removeChild(rootLayout); } + + return rootLayout; } export interface ComponentView { diff --git a/nativescript-angular/directives/tab-view.ts b/nativescript-angular/directives/tab-view.ts index 860b7adf6..984dc0076 100644 --- a/nativescript-angular/directives/tab-view.ts +++ b/nativescript-angular/directives/tab-view.ts @@ -1,5 +1,15 @@ -import { ElementRef, Directive, Input, TemplateRef, ViewContainerRef, OnInit, AfterViewInit } from "@angular/core"; +import { + AfterViewInit, + Directive, + ElementRef, + Input, + OnInit, + TemplateRef, + ViewContainerRef, +} from "@angular/core"; import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view"; + +import { CommentNode } from "../element-types"; import { convertToInt } from "../common/utils"; import { rendererLog } from "../trace"; import { isBlank } from "../lang-facade"; @@ -94,9 +104,9 @@ export class TabViewItemDirective implements OnInit { } const viewRef = this.viewContainer.createEmbeddedView(this.templateRef); - // Filter out text nodes, etc - const realViews = viewRef.rootNodes.filter((node) => - node.nodeName && node.nodeName !== "#text"); + // Filter out text nodes and comments + const realViews = viewRef.rootNodes.filter(node => + !(node instanceof CommentNode)); if (realViews.length > 0) { this.item.view = realViews[0]; diff --git a/nativescript-angular/element-registry.ts b/nativescript-angular/element-registry.ts index 534377b0c..fd889700f 100644 --- a/nativescript-angular/element-registry.ts +++ b/nativescript-angular/element-registry.ts @@ -1,31 +1,10 @@ -import { View } from "tns-core-modules/ui/core/view"; +import { ViewClass, ViewClassMeta } from "./element-types"; 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 { - nodeType: number; - nodeName: string; - templateParent: NgView; - ngCssClasses: Map; - meta: ViewClassMeta; -} - -export interface ViewClass { - new (): View; -} - -const defaultViewMeta: ViewClassMeta = { - skipAddToDom: false, -}; const elementMap = new Map(); const camelCaseSplit = /([a-z0-9])([A-Z])/g; +const defaultViewMeta: ViewClassMeta = { skipAddToDom: false }; export function registerElement( elementName: string, @@ -48,6 +27,7 @@ export function getViewClass(elementName: string): ViewClass { if (!entry) { throw new TypeError(`No known component for element ${elementName}.`); } + try { return entry.resolver(); } catch (e) { @@ -56,12 +36,8 @@ export function getViewClass(elementName: string): ViewClass { } 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; + return (entry && entry.meta) || defaultViewMeta; } export function isKnownView(elementName: string): boolean { @@ -110,10 +86,3 @@ registerElement("Span", () => require("tns-core-modules/text/span").Span); registerElement("DetachedContainer", () => require("tns-core-modules/ui/proxy-view-container").ProxyViewContainer, { skipAddToDom: true }); - -registerElement("DetachedText", () => require("ui/placeholder").Placeholder, - { skipAddToDom: true }); - -registerElement("Comment", () => require("ui/placeholder").Placeholder, - { skipAddToDom: false }); - diff --git a/nativescript-angular/element-types.ts b/nativescript-angular/element-types.ts new file mode 100644 index 000000000..e04833bfc --- /dev/null +++ b/nativescript-angular/element-types.ts @@ -0,0 +1,32 @@ +import { View } from "tns-core-modules/ui/core/view"; + +export type NgView = (View & ViewExtensions); +export type NgElement = NgView | CommentNode; + +export interface ViewExtensions { + nodeType: number; + nodeName: string; + templateParent: NgView; + ngCssClasses: Map; + meta: ViewClassMeta; +} + +export interface ViewClass { + new (): View; +} + +// used for creating comments and text nodes in the renderer +export class CommentNode { + meta: { skipAddToDom: true }; + templateParent: NgView; +} + +export interface ViewClassMeta { + skipAddToDom?: boolean; + insertChild?: (parent: NgView, child: NgView, atIndex: number) => void; + removeChild?: (parent: NgView, child: NgView) => void; +} + +export function isDetachedElement(element): boolean { + return (element && element.meta && element.meta.skipAddToDom); +} diff --git a/nativescript-angular/index.ts b/nativescript-angular/index.ts index e1309f312..8ec8eaa23 100644 --- a/nativescript-angular/index.ts +++ b/nativescript-angular/index.ts @@ -1,4 +1,4 @@ -import "application"; +import "tns-core-modules/application"; export * from "./platform-common"; export * from "./platform"; @@ -15,13 +15,18 @@ export * from "./modal-dialog"; export * from "./renderer"; export * from "./view-util"; export * from "./resource-loader"; + export { ViewResolver, - ViewClass, - ViewClassMeta, registerElement, getViewClass, getViewMeta, isKnownView, } from "./element-registry"; + +export { + ViewClass, + ViewClassMeta, +} from "./element-types"; + export * from "./value-accessors/base-value-accessor"; diff --git a/nativescript-angular/renderer.ts b/nativescript-angular/renderer.ts index 9773b0bf9..1a9f0bfbc 100644 --- a/nativescript-angular/renderer.ts +++ b/nativescript-angular/renderer.ts @@ -12,7 +12,7 @@ import { topmost } from "tns-core-modules/ui/frame"; import { APP_ROOT_VIEW, DEVICE, getRootPage } from "./platform-providers"; import { isBlank } from "./lang-facade"; import { ViewUtil } from "./view-util"; -import { NgView } from "./element-registry"; +import { NgView, CommentNode } from "./element-types"; import { rendererLog as traceLog } from "./trace"; // CONTENT_ATTR not exported from NativeScript_renderer - we need it for styles application. @@ -43,6 +43,7 @@ export class NativeScriptRendererFactory implements RendererFactory2 { if (!rootView) { rootView = getRootPage() || topmost().currentPage; } + rootView.nodeName = "NONE"; this.rootNgView = rootView; } @@ -83,26 +84,17 @@ export class NativeScriptRenderer extends Renderer2 { appendChild(parent: any, newChild: NgView): void { traceLog(`NativeScriptRenderer.appendChild child: ${newChild} parent: ${parent}`); - - if (parent) { - this.viewUtil.insertChild(parent, newChild); - } + this.viewUtil.insertChild(parent, newChild); } insertBefore(parent: NgView, newChild: NgView, refChildIndex: number): void { traceLog(`NativeScriptRenderer.insertBefore child: ${newChild} parent: ${parent}`); - - if (parent) { - this.viewUtil.insertChild(parent, newChild, refChildIndex); - } + this.viewUtil.insertChild(parent, newChild, refChildIndex); } removeChild(parent: any, oldChild: NgView): void { traceLog(`NativeScriptRenderer.removeChild child: ${oldChild} parent: ${parent}`); - - if (parent) { - this.viewUtil.removeChild(parent, oldChild); - } + this.viewUtil.removeChild(parent, oldChild); } selectRootElement(selector: string): NgView { @@ -111,7 +103,7 @@ export class NativeScriptRenderer extends Renderer2 { } parentNode(node: NgView): any { - return node.parent; + return node.parent || node.templateParent; } nextSibling(node: NgView): number { @@ -119,7 +111,7 @@ export class NativeScriptRenderer extends Renderer2 { return this.viewUtil.nextSiblingIndex(node); } - createComment(_value: any) { + createComment(_value: any): CommentNode { traceLog(`NativeScriptRenderer.createComment ${_value}`); return this.viewUtil.createComment(); } @@ -129,7 +121,7 @@ export class NativeScriptRenderer extends Renderer2 { return this.viewUtil.createView(name); } - createText(_value: string) { + createText(_value: string): CommentNode { traceLog(`NativeScriptRenderer.createText ${_value}`); return this.viewUtil.createText(); } diff --git a/nativescript-angular/view-util.ts b/nativescript-angular/view-util.ts index a395e961f..f0b9cc73a 100644 --- a/nativescript-angular/view-util.ts +++ b/nativescript-angular/view-util.ts @@ -7,9 +7,15 @@ import { getViewClass, getViewMeta, isKnownView, +} from "./element-registry"; + +import { + CommentNode, ViewExtensions, + NgElement, NgView, -} from "./element-registry"; + isDetachedElement, +} from "./element-types"; import { platformNames, Device } from "tns-core-modules/platform"; import { rendererLog as traceLog } from "./trace"; @@ -47,8 +53,13 @@ export class ViewUtil { this.isAndroid = device.os === platformNames.android; } - public insertChild(parent: any, child: NgView, atIndex: number = -1) { - if (!parent || child.meta.skipAddToDom) { + public insertChild(parent: any, child: NgElement, atIndex: number = -1) { + if (child instanceof CommentNode) { + child.templateParent = parent; + return; + } + + if (!parent || isDetachedElement(child)) { return; } @@ -56,7 +67,7 @@ export class ViewUtil { parent.meta.insertChild(parent, child, atIndex); } else if (isLayout(parent)) { if (child.parent === parent) { - let index = (parent).getChildIndex(child); + const index = (parent).getChildIndex(child); if (index !== -1) { parent.removeChild(child); } @@ -67,12 +78,7 @@ export class ViewUtil { parent.addChild(child); } } else if (isContentView(parent)) { - // Explicit handling of template anchors inside ContentView - if (child.nodeName === "#comment") { - parent._addView(child, atIndex); - } else { - parent.content = child; - } + parent.content = child; } else if (parent && parent._addChildFromBuilder) { parent._addChildFromBuilder(child.nodeName, child); } else { @@ -80,8 +86,11 @@ export class ViewUtil { } } - public removeChild(parent: any, child: NgView) { - if (!parent || child.meta.skipAddToDom) { + public removeChild(parent: any, child: NgElement) { + if (!parent || + child instanceof CommentNode || + isDetachedElement(child)) { + return; } @@ -93,11 +102,6 @@ export class ViewUtil { if (parent.content === child) { parent.content = null; } - - // Explicit handling of template anchors inside ContentView - if (child.nodeName === "#comment") { - parent._removeView(child); - } } else if (isView(parent)) { parent._removeView(child); } else { @@ -115,20 +119,12 @@ export class ViewUtil { } } - public createComment(): NgView { - const commentView = this.createView("Comment"); - commentView.nodeName = "#comment"; - commentView.visibility = "collapse"; - - return commentView; + public createComment(): CommentNode { + return new CommentNode(); } - public createText(): NgView { - const detachedText = this.createView("DetachedText"); - detachedText.nodeName = "#text"; - detachedText.visibility = "collapse"; - - return detachedText; + public createText(): CommentNode { + return new CommentNode(); } public createView(name: string): NgView { @@ -137,6 +133,7 @@ export class ViewUtil { if (!isKnownView(name)) { name = "ProxyViewContainer"; } + const viewClass = getViewClass(name); let view = new viewClass(); view.nodeName = name; diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index 3f803858a..27679de61 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -128,13 +128,13 @@ const customPageFactoryProvider = { // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PageRouterOutletAppComponent)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PageRouterOutletNestedAppComponent)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ClearHistoryAppComponent)); -// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(LoginAppComponent)); +//platformNativeScriptDynamic().bootstrapModule(makeExampleModule(LoginAppComponent)); // animations // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(AnimationStatesTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(AnimationNgClassTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(AnimationKeyframesTest)); -platformNativeScriptDynamic().bootstrapModule(makeExampleModule(AnimationEnterLeaveTest)); +// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(AnimationEnterLeaveTest)); // Livesync test let cachedUrl: string; diff --git a/ng-sample/app/examples/renderer-test.html b/ng-sample/app/examples/renderer-test.html index 674a1b4b3..b0c17d6f8 100644 --- a/ng-sample/app/examples/renderer-test.html +++ b/ng-sample/app/examples/renderer-test.html @@ -1,28 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + diff --git a/ng-sample/package.json b/ng-sample/package.json index 5340da35d..c1f91caf3 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -2,10 +2,10 @@ "nativescript": { "id": "org.nativescript.ngsample", "tns-android": { - "version": "2.5.0" + "version": "3.0.0" }, "tns-ios": { - "version": "2.5.0" + "version": "3.0.0" } }, "name": "tns-template-hello-world", @@ -53,10 +53,9 @@ "filewalker": "0.1.2", "lazy": "1.0.11", "nativescript-dev-typescript": "^0.3.1", - "nativescript-dev-webpack": "0.0.13", "shelljs": "^0.7.0", "tslint": "^4.5.1", - "typescript": "~2.2.0" + "typescript": "~2.3.2" }, "scripts": { "tslint": "tslint --project tsconfig.json --config tslint.json" diff --git a/tests/app/tests/property-sets.ts b/tests/app/tests/property-sets.ts index 88472109e..3cb2ca29d 100644 --- a/tests/app/tests/property-sets.ts +++ b/tests/app/tests/property-sets.ts @@ -2,7 +2,7 @@ import {assert} from "./test-config"; import {View} from "ui/core/view"; import {ViewUtil} from "nativescript-angular/view-util"; -import {NgView, ViewExtensions, ViewClassMeta} from "nativescript-angular/element-registry"; +import {NgView, ViewExtensions, ViewClassMeta} from "nativescript-angular/element-types"; import {Red} from "color/known-colors"; import {device, platformNames} from "platform"; import {createDevice} from "./test-utils"; diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index 779c79cee..bce870fd1 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -9,7 +9,7 @@ import { LayoutBase } from "ui/layouts/layout-base"; import { StackLayout } from "ui/layouts/stack-layout"; import { ContentView } from "ui/content-view"; import { Button } from "ui/button"; -import { NgView } from "nativescript-angular/element-registry"; +import { NgView } from "nativescript-angular/element-types"; @Component({ template: `` @@ -94,6 +94,48 @@ export class NgIfLabel { } } +@Component({ + selector: "ng-if-else", + template: ` + + + + + + + + ` +}) +export class NgIfElseComponent { + public show: boolean = true; + constructor(public elementRef: ElementRef) { + } +} + + +@Component({ + selector: "ng-if-then-else", + template: ` + + + + + + + + + + + + + ` +}) +export class NgIfThenElseComponent { + public show: boolean = true; + constructor(public elementRef: ElementRef) { + } +} + @Component({ selector: "ng-for-label", template: `` @@ -112,10 +154,10 @@ describe("Renderer E2E", () => { LayoutWithLabel, LabelCmp, LabelContainer, ProjectableCmp, ProjectionContainer, StyledLabelCmp, StyledLabelCmp2, - NgIfLabel, NgForLabel, + NgIfLabel, NgIfElseComponent, NgIfThenElseComponent, + NgForLabel, ]).then((app) => { testApp = app; - }); }); @@ -214,7 +256,7 @@ describe("Renderer E2E", () => { it("ngIf hides component when false", () => { return testApp.loadComponent(NgIfLabel).then((componentRef) => { const componentRoot = componentRef.instance.elementRef.nativeElement; - assert.equal("(ProxyViewContainer (#comment))", dumpView(componentRoot)); + assert.equal("(ProxyViewContainer)", dumpView(componentRoot)); }); }); @@ -225,7 +267,69 @@ describe("Renderer E2E", () => { component.show = true; testApp.appRef.tick(); - assert.equal("(ProxyViewContainer (#comment), (Label))", dumpView(componentRoot)); + assert.equal("(ProxyViewContainer (Label))", dumpView(componentRoot)); + }); + }); + + it("ngIfElse show 'if' template when condition is true", () => { + return testApp.loadComponent(NgIfElseComponent).then(componentRef => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer " + + "(StackLayout " + + "(Label[text=If])))", // the content to be displayed + + dumpView(componentRoot, true)); + }); + }); + + it("ngIfElse show 'else' template when condition is false", () => { + return testApp.loadComponent(NgIfElseComponent).then(componentRef => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + component.show = false; + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer " + + "(StackLayout " + + "(Label[text=Else])))", // the content to be displayed + + dumpView(componentRoot, true)); + }); + }); + + it("ngIfThenElse show 'then' template when condition is true", () => { + return testApp.loadComponent(NgIfThenElseComponent).then(componentRef => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer " + + "(StackLayout " + + "(Label[text=Then])))", // the content to be displayed + dumpView(componentRoot, true)); + }); + }); + + + it("ngIfThenElse show 'else' template when condition is false", () => { + return testApp.loadComponent(NgIfThenElseComponent).then(componentRef => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + component.show = false; + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer " + + "(StackLayout " + + "(Label[text=Else])))", // the content to be displayed + + dumpView(componentRoot, true)); }); }); @@ -233,7 +337,7 @@ describe("Renderer E2E", () => { return testApp.loadComponent(NgForLabel).then((componentRef) => { const componentRoot = componentRef.instance.elementRef.nativeElement; assert.equal( - "(ProxyViewContainer (#comment), (Label[text=one]), (Label[text=two]), (Label[text=three]))", + "(ProxyViewContainer (Label[text=one]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true)); }); }); @@ -247,7 +351,7 @@ describe("Renderer E2E", () => { testApp.appRef.tick(); assert.equal( - "(ProxyViewContainer (#comment), (Label[text=one]), (Label[text=three]))", + "(ProxyViewContainer (Label[text=one]), (Label[text=three]))", dumpView(componentRoot, true)); }); }); @@ -261,7 +365,7 @@ describe("Renderer E2E", () => { testApp.appRef.tick(); assert.equal( - "(ProxyViewContainer (#comment), " + + "(ProxyViewContainer " + "(Label[text=one]), (Label[text=new]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true)); }); From e0f38876608a374e3db44b782eaaaa7775fbf983 Mon Sep 17 00:00:00 2001 From: SvetoslavTsenov Date: Wed, 10 May 2017 13:09:25 +0300 Subject: [PATCH 09/17] Update .travis.yml Change args for running nativescript-dev-appium --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e9ad43870..53833380b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ script: - - tns build android - android-wait-for-emulator -- npm run run-appium-android-23 +- npm run appium --runtype=23 before_deploy: - cd ../nativescript-angular - npm install -g nativescript --ignore-scripts From 03a9255a6f97cdaee65d25033ef8f4452298ad25 Mon Sep 17 00:00:00 2001 From: SvetoslavTsenov Date: Wed, 10 May 2017 13:11:39 +0300 Subject: [PATCH 10/17] Update package.json Update nativescirpt-dev-appium plugin to latest --- tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/package.json b/tests/package.json index 0b894576e..36d5cf0b7 100644 --- a/tests/package.json +++ b/tests/package.json @@ -56,7 +56,7 @@ "karma-nativescript-launcher": "^0.4.0", "lazy": "1.0.11", "mocha": "^2.4.5", - "nativescript-dev-appium": "0.0.14", + "nativescript-dev-appium": "^0.3.0", "nativescript-dev-typescript": "^0.4.0", "socket.io": "1.4.8", "socket.io-client": "1.4.8", From 427ff0593ddf73adc92c3ad885f103c737c43817 Mon Sep 17 00:00:00 2001 From: SvetoslavTsenov Date: Wed, 10 May 2017 13:41:50 +0300 Subject: [PATCH 11/17] Update .travis.yml Update --runtype=android23 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 53833380b..56bda56a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,14 +33,14 @@ install: - npm install - tns platform add android before_script: -- echo no | android create avd --force -n test -t android-19 -b armeabi-v7a +- echo no | android create avd --force -n test -t android-23 -b armeabi-v7a - emulator -memory 1024 -avd test -no-audio -no-window & script: - - - tns build android - android-wait-for-emulator -- npm run appium --runtype=23 +- npm run appium --runtype=android23 before_deploy: - cd ../nativescript-angular - npm install -g nativescript --ignore-scripts From 39d9b29937b47f7c57b82c40df9b340680054e71 Mon Sep 17 00:00:00 2001 From: SvetoslavTsenov Date: Wed, 10 May 2017 13:54:06 +0300 Subject: [PATCH 12/17] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 56bda56a1..f186db267 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ jdk: android: components: - platform-tools - - build-tools-23.0.1 + - build-tools-23.0.2 - android-23 - extra-android-m2repository - sys-img-armeabi-v7a-android-23 @@ -33,7 +33,7 @@ install: - npm install - tns platform add android before_script: -- echo no | android create avd --force -n test -t android-23 -b armeabi-v7a +- echo no | android create avd --force -n test -t android-23 -abi armeabi-v7a - emulator -memory 1024 -avd test -no-audio -no-window & script: - From d4d8d33ec47b2f75100edc828c4fdc49ea3615ca Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Fri, 19 May 2017 13:25:02 +0300 Subject: [PATCH 13/17] refactor(NSModuleFactoryLoader): remove compileModuleAndAllComponentsAsync That method is internal for Angular and available only within the JiT compiler and we shouldn't expose it to user because it won't work within AoT compiled apps. --- .../router/ns-module-factory-loader.ts | 66 ++++++++----------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/nativescript-angular/router/ns-module-factory-loader.ts b/nativescript-angular/router/ns-module-factory-loader.ts index beca86f5b..a64868808 100644 --- a/nativescript-angular/router/ns-module-factory-loader.ts +++ b/nativescript-angular/router/ns-module-factory-loader.ts @@ -1,12 +1,11 @@ import { - Injectable, Compiler, + Injectable, NgModuleFactory, NgModuleFactoryLoader, - ModuleWithComponentFactories, SystemJsNgModuleLoader, + Type, } from "@angular/core"; - import { path, knownFolders } from "tns-core-modules/file-system"; const SEPARATOR = "#"; @@ -15,63 +14,50 @@ const SEPARATOR = "#"; export class NSModuleFactoryLoader implements NgModuleFactoryLoader { private offlineMode: boolean; - constructor(private compiler: Compiler, private ngModuleLoader: SystemJsNgModuleLoader) { + constructor( + private compiler: Compiler, + private ngModuleLoader: SystemJsNgModuleLoader, + ) { this.offlineMode = compiler instanceof Compiler; } load(path: string): Promise> { - if (this.offlineMode) { - return this.ngModuleLoader.load(path); - } else { - return this.loadAndCompile(path); - } + return this.offlineMode ? + this.ngModuleLoader.load(path) : + this.loadAndCompile(path); } - /** - * When needing the module with component factories - * Example: lazy loading on demand via user actions instead of routing - * Provides access to components in the lazy loaded module right away - * @param path module path - */ - public loadAndCompileComponents(path: string): Promise { - return this.loadAndCompile(path, true); + private loadAndCompile(path: string): Promise> { + const module = requireModule(path); + return Promise.resolve(this.compiler.compileModuleAsync(module)); } +} - private loadAndCompile(path: string, includeComponents?: boolean): - Promise | ModuleWithComponentFactories> { - let {modulePath, exportName} = splitPath(path); - - let loadedModule = global.require(modulePath)[exportName]; - checkNotEmpty(loadedModule, modulePath, exportName); +function requireModule(path: string): Type { + const {modulePath, exportName} = splitPath(path); - if (includeComponents) { - return Promise.resolve(this.compiler.compileModuleAndAllComponentsAsync(loadedModule)); - } else { - return Promise.resolve(this.compiler.compileModuleAsync(loadedModule)); - } - } + const loadedModule = global.require(modulePath)[exportName]; + checkNotEmpty(loadedModule, modulePath, exportName); + return loadedModule; } function splitPath(path: string): {modulePath: string, exportName: string} { - let [modulePath, exportName] = path.split(SEPARATOR); - modulePath = getAbsolutePath(modulePath); - - if (typeof exportName === "undefined") { - exportName = "default"; - } + const [relativeModulePath, exportName = "default"] = path.split(SEPARATOR); + const absoluteModulePath = getAbsolutePath(relativeModulePath); - return {modulePath, exportName}; + return {modulePath: absoluteModulePath, exportName}; } function getAbsolutePath(relativePath: string) { - return path.normalize(path.join(knownFolders.currentApp().path, relativePath)); + const projectPath = knownFolders.currentApp().path; + const absolutePath = path.join(projectPath, relativePath); + + return path.normalize(absolutePath); } -function checkNotEmpty(value: any, modulePath: string, exportName: string): any { +function checkNotEmpty(value: any, modulePath: string, exportName: string): void { if (!value) { throw new Error(`Cannot find '${exportName}' in '${modulePath}'`); } - - return value; } From 22f982b9501348b46695ea950eb8b54f327f06ab Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Fri, 19 May 2017 14:00:30 +0300 Subject: [PATCH 14/17] refactor(dialogs): pass show modal args as objects --- nativescript-angular/directives/dialogs.ts | 87 ++++++++++++++-------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/nativescript-angular/directives/dialogs.ts b/nativescript-angular/directives/dialogs.ts index 2fb756e95..8012cf1d1 100644 --- a/nativescript-angular/directives/dialogs.ts +++ b/nativescript-angular/directives/dialogs.ts @@ -1,9 +1,17 @@ import { - ReflectiveInjector, ComponentFactoryResolver, ViewContainerRef, NgModuleRef, - Type, Injectable, ComponentRef, Directive + ComponentFactoryResolver, + ComponentRef, + Directive, + Injectable, + NgModuleRef, + ReflectiveInjector, + Type, + ViewContainerRef, } from "@angular/core"; + import { Page } from "tns-core-modules/ui/page"; import { View } from "tns-core-modules/ui/core/view"; + import { DetachedLoader } from "../common/detached-loader"; import { PageFactory, PAGE_FACTORY } from "../platform-providers"; @@ -21,44 +29,61 @@ export class ModalDialogParams { } } +interface ShowDialogOptions { + containerRef: ViewContainerRef; + context: any; + doneCallback; + fullscreen: boolean; + pageFactory: PageFactory; + parentPage: Page; + resolver: ComponentFactoryResolver; + type: Type; +} + @Injectable() export class ModalDialogService { - public showModal(type: Type, options: ModalDialogOptions): Promise { - if (!options.viewContainerRef) { + public showModal(type: Type, + {viewContainerRef, moduleRef, context, fullscreen}: ModalDialogOptions + ): Promise { + if (!viewContainerRef) { throw new Error( - "No viewContainerRef: Make sure you pass viewContainerRef in ModalDialogOptions."); + "No viewContainerRef: " + + "Make sure you pass viewContainerRef in ModalDialogOptions." + ); } - const viewContainerRef = options.viewContainerRef; const parentPage: Page = viewContainerRef.injector.get(Page); + const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY); + // resolve from particular module (moduleRef) // or from same module as parentPage (viewContainerRef) - const resolver: ComponentFactoryResolver = (options.moduleRef || viewContainerRef).injector.get( - ComponentFactoryResolver); - const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY); + const componentContainer = moduleRef || viewContainerRef; + const resolver = componentContainer.injector.get(ComponentFactoryResolver); - return new Promise((resolve) => { - setTimeout(() => ModalDialogService.showDialog( - type, - options, - resolve, - viewContainerRef, - resolver, + return new Promise(resolve => { + setTimeout(() => ModalDialogService.showDialog({ + containerRef: viewContainerRef, + context, + doneCallback: resolve, + fullscreen, + pageFactory, parentPage, - pageFactory - ), 10); + resolver, + type, + }), 10); }); } - private static showDialog( - type: Type, - options: ModalDialogOptions, + private static showDialog({ + containerRef, + context, doneCallback, - containerRef: ViewContainerRef, - resolver: ComponentFactoryResolver, - parentPage: Page, - pageFactory: PageFactory): void { - + fullscreen, + pageFactory, + parentPage, + resolver, + type, + }: ShowDialogOptions): void { const page = pageFactory({ isModal: true, componentType: type }); let detachedLoaderRef: ComponentRef; @@ -69,7 +94,7 @@ export class ModalDialogService { detachedLoaderRef.destroy(); }; - const modalParams = new ModalDialogParams(options.context, closeCallback); + const modalParams = new ModalDialogParams(context, closeCallback); const providers = ReflectiveInjector.resolve([ { provide: Page, useValue: page }, @@ -88,7 +113,7 @@ export class ModalDialogService { } page.content = componentView; - parentPage.showModal(page, options.context, closeCallback, options.fullscreen); + parentPage.showModal(page, context, closeCallback, fullscreen); }); } } @@ -99,7 +124,9 @@ export class ModalDialogService { }) export class ModalDialogHost { // tslint:disable-line:directive-class-suffix constructor() { - throw new Error("ModalDialogHost is deprecated. Call ModalDialogService.showModal() " + - "by passing ViewContainerRef in the options instead."); + throw new Error("ModalDialogHost is deprecated. " + + "Call ModalDialogService.showModal() " + + "by passing ViewContainerRef in the options instead." + ); } } From 9068c4684eec85767631f3e8cfdf473a3c607ee7 Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Fri, 19 May 2017 15:17:21 +0300 Subject: [PATCH 15/17] fix: provide SystemJsNgModuleLoader in NativeScriptModule instead of NativeScriptRouterModule SystemJsNgModuleLoader is injected in NSModuleFactoryLoader. That loader can be used without router, so we need to provide the systemjs token in the root NativeScriptModule instead. --- nativescript-angular/nativescript.module.ts | 27 +++++++++++++-------- nativescript-angular/router.ts | 2 -- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/nativescript-angular/nativescript.module.ts b/nativescript-angular/nativescript.module.ts index 521e926ee..2405ef605 100644 --- a/nativescript-angular/nativescript.module.ts +++ b/nativescript-angular/nativescript.module.ts @@ -8,19 +8,25 @@ import "./polyfills/array"; import "./polyfills/console"; import { CommonModule } from "@angular/common"; -import { NativeScriptRendererFactory } from "./renderer"; -import { DetachedLoader } from "./common/detached-loader"; -import { ModalDialogHost, ModalDialogService } from "./directives/dialogs"; import { ApplicationModule, ErrorHandler, + NO_ERRORS_SCHEMA, + NgModule, RendererFactory2, - NgModule, NO_ERRORS_SCHEMA, + SystemJsNgModuleLoader, } from "@angular/core"; + +import { NativeScriptRendererFactory } from "./renderer"; +import { DetachedLoader } from "./common/detached-loader"; import { - defaultPageProvider, + ModalDialogHost, + ModalDialogService, +} from "./directives/dialogs"; +import { + defaultDeviceProvider, defaultFrameProvider, - defaultDeviceProvider + defaultPageProvider, } from "./platform-providers"; import { NS_DIRECTIVES } from "./directives"; @@ -35,13 +41,14 @@ export function errorHandlerFactory() { ...NS_DIRECTIVES, ], providers: [ - { provide: ErrorHandler, useFactory: errorHandlerFactory }, + ModalDialogService, + NativeScriptRendererFactory, + SystemJsNgModuleLoader, + defaultDeviceProvider, defaultFrameProvider, defaultPageProvider, - defaultDeviceProvider, - NativeScriptRendererFactory, + { provide: ErrorHandler, useFactory: errorHandlerFactory }, { provide: RendererFactory2, useClass: NativeScriptRendererFactory }, - ModalDialogService ], entryComponents: [ DetachedLoader, diff --git a/nativescript-angular/router.ts b/nativescript-angular/router.ts index 08bc0c470..c61228382 100644 --- a/nativescript-angular/router.ts +++ b/nativescript-angular/router.ts @@ -4,7 +4,6 @@ import { NO_ERRORS_SCHEMA, Optional, SkipSelf, - SystemJsNgModuleLoader, } from "@angular/core"; import { RouterModule, Routes, ExtraOptions } from "@angular/router"; import { LocationStrategy, PlatformLocation } from "@angular/common"; @@ -38,7 +37,6 @@ export type LocationState = LocationState; NativescriptPlatformLocation, { provide: PlatformLocation, useClass: NativescriptPlatformLocation }, RouterExtensions, - SystemJsNgModuleLoader, ], imports: [ RouterModule, From 9ef475f801fb5f2d1086fc15af180e2e601a34a8 Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Fri, 19 May 2017 16:26:52 +0300 Subject: [PATCH 16/17] test: fix date unit test assert value --- tests/app/tests/value-accessor-tests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/app/tests/value-accessor-tests.ts b/tests/app/tests/value-accessor-tests.ts index ac16c7eaa..0f55fcba2 100644 --- a/tests/app/tests/value-accessor-tests.ts +++ b/tests/app/tests/value-accessor-tests.ts @@ -102,7 +102,7 @@ describe("two-way binding via ng-model", () => { assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on empty"); accessor.writeValue("2010-03-17"); - assert.equal(formatDate(new Date(2010, 2, 16)), formatDate(accessor.view.date)); + assert.equal(formatDate(new Date(2010, 2, 17)), formatDate(accessor.view.date)); accessor.writeValue("a fortnight ago"); assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on parse error"); From 000ddf79dec7149940e1cca446925d5ad59eb5df Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Fri, 19 May 2017 16:33:46 +0300 Subject: [PATCH 17/17] test: remove lazy modal load unit test we'll use e2e test for this functionality instead --- tests/app/tests/modal-dialog.ts | 72 ++------------------------------- 1 file changed, 4 insertions(+), 68 deletions(-) diff --git a/tests/app/tests/modal-dialog.ts b/tests/app/tests/modal-dialog.ts index 2e08868c5..c14a13f36 100644 --- a/tests/app/tests/modal-dialog.ts +++ b/tests/app/tests/modal-dialog.ts @@ -1,17 +1,10 @@ // make sure you import mocha-config before @angular/core import { assert } from "./test-config"; -import { TestApp, bootstrapTestApp } from "./test-app"; -import { Location, LocationStrategy } from "@angular/common"; -import { Component, ViewContainerRef, NgModuleFactoryLoader, ModuleWithComponentFactories, ComponentFactory, Compiler, Injector, Optional } from "@angular/core"; -import { NoPreloading, PreloadingStrategy, ROUTES, Route, Router, RouterModule, RouterOutletMap, Routes, UrlHandlingStrategy, UrlSerializer, provideRoutes, ɵROUTER_PROVIDERS as ROUTER_PROVIDERS, ɵflatten as flatten } from '@angular/router'; -import { BehaviorSubject } from "rxjs/BehaviorSubject"; +import { TestApp } from "./test-app"; +import { Component, ViewContainerRef } from "@angular/core"; import { Page } from "ui/page"; import { topmost } from "ui/frame"; import { ModalDialogParams, ModalDialogService } from "nativescript-angular/directives/dialogs"; -import { NSModuleFactoryLoader } from "nativescript-angular/router"; -import { HOOKS_LOG } from "../base.component"; -const lazyLoadHooksLog = new BehaviorSubject([]); -const lazyLoadHooksLogProvider = { provide: HOOKS_LOG, useValue: lazyLoadHooksLog }; import { device, platformNames } from "platform"; const CLOSE_WAIT = (device.os === platformNames.ios) ? 1000 : 0; @@ -40,41 +33,16 @@ export class FailComponent { } } -// TODO: this is done temporarily since the SecondModule is used to lazily load on demand here in the tests -// could create module specificly to test this -export function setupTestingRouter( - urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, - loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], - urlHandlingStrategy?: UrlHandlingStrategy) { - const router = new Router( - null !, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes)); - if (urlHandlingStrategy) { - router.urlHandlingStrategy = urlHandlingStrategy; - } - return router; -} - @Component({ selector: "sucess-comp", - providers: [ - ModalDialogService, - { - provide: Router, useFactory: setupTestingRouter, - deps: [ - UrlSerializer, RouterOutletMap, Location, NgModuleFactoryLoader, Compiler, Injector, ROUTES, - [UrlHandlingStrategy, new Optional()] - ] - }, - lazyLoadHooksLogProvider, - { provide: NgModuleFactoryLoader, useClass: NSModuleFactoryLoader } - ], + providers: [ModalDialogService], template: ` ` }) export class SuccessComponent { - constructor(public service: ModalDialogService, public vcRef: ViewContainerRef, public moduleLoader: NgModuleFactoryLoader) { + constructor(public service: ModalDialogService, public vcRef: ViewContainerRef) { } } @@ -141,36 +109,4 @@ describe("modal-dialog", () => { setTimeout(done, CLOSE_WAIT); // wait for the dialog to close in IOS }, err => done(err)); }); - - it("showModal provides module reference option when opening modal component which comes from lazy loaded module", (done) => { - const context = { property: "I was lazy loaded from another module on demand!" }; - let service, comp; - testApp.loadComponent(SuccessComponent) - .then((ref) => { - service = ref.instance.service; - comp = ref.instance; - return (comp.moduleLoader).loadAndCompileComponents("./lazy-loaded.module#SecondModule"); - }).then((mod: any) => { - const moduleRef = (>mod).ngModuleFactory.create(comp.vcRef.parentInjector); - // find component factory to ref the correct componentType - let lazyModalCmpFactory: ComponentFactory; - for (let cmp of mod.componentFactories) { - if (cmp.selector === "modal-lazy-comp") { // find by selector - lazyModalCmpFactory = cmp; - break; - } - } - - return service.showModal(lazyModalCmpFactory.componentType, { - moduleRef, - viewContainerRef: comp.vcRef, - context: context - }); - }) - .then((res) => { - assert.strictEqual(res, context); - setTimeout(done, CLOSE_WAIT); // wait for the dialog to close in IOS - }, err => done(err)); - - }); });