diff --git a/.travis.yml b/.travis.yml index 09ea3d370..fc289f2cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,12 @@ env: global: - NODE_VERSION=6.9.1 - - DATE=$(date +%Y-%m-%d) - - PACKAGE_VERSION=$DATE-$TRAVIS_BUILD_NUMBER - EMULATOR_API_LEVEL=19 - ANDROID_VERSION=23 - ANDROID_BUILD_TOOLS_VERSION=23.0.1 - ANDROID_ABI=armeabi-v7a - ANDROID_TAG=google_apis - - APPIUM_VERSION=1.6.3 + - APPIUM_VERSION=1.6.5 language: android jdk: - oraclejdk8 @@ -38,27 +36,12 @@ install: - npm run tslint - cd ../tests - npm install +- npm i appium@$APPIUM_VERSION before_script: - echo no | android create avd --force -n test -t android-$EMULATOR_API_LEVEL --abi $ANDROID_ABI - emulator -memory 1024 -avd test -no-audio -no-window & - android-wait-for-emulator script: -- -- - tns build android - android-wait-for-emulator -- npm run run-appium-android -before_deploy: -- cd ../nativescript-angular -- npm install -g nativescript --ignore-scripts -- tns usage-reporting disable -- tns error-reporting disable -- node ../build/travis-scripts/add-publishConfig.js next $PACKAGE_VERSION -deploy: - provider: npm - email: nativescript@telerik.com - skip_cleanup: true - api_key: - secure: J88MqLAoZStZZ77AAf+wgaoZp+8zG3fOUHRneSe4x/yEzyUShS9SlGuq0TSkm9sJVX94iHJl1BQ4yjLshOPV9dkOg1+BB4PbsDTKPCAhPCZgpW7WKz6iImmuWHArchLIRtI1fp+UYi1+V6c7gLALQPY7qR2QJcDJdq1tdgORAyGySMis95ttVhnn6DWTBbs/ocu+IzgOyBSkIiZR0mGk7q/pmVQPy+XL5PQoyUOhD4MmvAAIeVr+XoZ5I8pAUwhi1/bZijXrzWe7LbXh8pTDlEWvYduzYYjJZqUrHiE/e1e8/DIPXGaBUQBj7LRxSqqO8AJXGeCg4DF1R9j4CSG5c0pAwQ/U6vOGu8duPEGaoKG5+HlrTav7gI/YbwFA5HKyh1uzQ5trZDJ4mMKUoB1+8/eL2cjLudtyBB2Kg28wH6f78A9mQC1EJcP7Jz3qJTSUyhczIvwSF8/EkD8xmeaoTi2e+4TNgf7pys1cp6c7m7zKZbvVy25lfyAfG1rCF5+rzKj+GnE9mtLaY6VvlKWjyxklh8hfRBC94TZ8K7PH0tmdgk2Jal+OCdm9FDdmNrBSC1G/gPS8PchtffIRprPhNAUfcVpdg0rlQ4dckbGRbB5UBgwHkpoKasaSTx/nO85AiK6USIYOIod19loXUBvN3QyHUX76w265UhmTnb8iojo= - on: - branch: master \ No newline at end of file +- npm run appium --runtype=android19 --appium=$APPIUM_VERSION diff --git a/CHANGELOG.md b/CHANGELOG.md index aa037c81d..2ce916fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ + +## [3.1.1](https://github.com/NativeScript/nativescript-angular/compare/3.1.0...3.1.1) (2017-06-29) + + +### Bug Fixes + +* **forms:** add directives for formControl ([#861](https://github.com/NativeScript/nativescript-angular/issues/861)) ([#864](https://github.com/NativeScript/nativescript-angular/issues/864)) ([d29c8e1](https://github.com/NativeScript/nativescript-angular/commit/d29c8e1)) + + + + +# [3.1.0](https://github.com/NativeScript/nativescript-angular/compare/3.0.0...3.1.0) (2017-06-19) + + +### Bug Fixes + +* **animations:** use parsers from core modules ([#844](https://github.com/NativeScript/nativescript-angular/issues/844)) ([1abebb6](https://github.com/NativeScript/nativescript-angular/commit/1abebb6)), closes [#738](https://github.com/NativeScript/nativescript-angular/issues/738) +* **dom-adapter:** add fake implementation for getUserAgent ([#835](https://github.com/NativeScript/nativescript-angular/issues/835)) ([743131c](https://github.com/NativeScript/nativescript-angular/commit/743131c)), closes [#831](https://github.com/NativeScript/nativescript-angular/issues/831) +* **forms:** add (touch) event and [disabled] property for controls ([#836](https://github.com/NativeScript/nativescript-angular/issues/836)) ([c8a6404](https://github.com/NativeScript/nativescript-angular/commit/c8a6404)), closes [#804](https://github.com/NativeScript/nativescript-angular/issues/804) +* **ns-router-link:** convert clearHistory string to boolean ([#834](https://github.com/NativeScript/nativescript-angular/issues/834)) ([ff99984](https://github.com/NativeScript/nativescript-angular/commit/ff99984)), closes [#832](https://github.com/NativeScript/nativescript-angular/issues/832) +* **renderer:** add styles when ViewEncapsulation is None ([#812](https://github.com/NativeScript/nativescript-angular/issues/812)) ([8d013e2](https://github.com/NativeScript/nativescript-angular/commit/8d013e2)), closes [#794](https://github.com/NativeScript/nativescript-angular/issues/794) +* **renderer:** set templateParent to comment and text nodes ([#785](https://github.com/NativeScript/nativescript-angular/issues/785)) ([b127ba7](https://github.com/NativeScript/nativescript-angular/commit/b127ba7)), closes [#777](https://github.com/NativeScript/nativescript-angular/issues/777) [#787](https://github.com/NativeScript/nativescript-angular/issues/787) +* **renderer:** stop performing value conversions ([#806](https://github.com/NativeScript/nativescript-angular/issues/806)) ([354074d](https://github.com/NativeScript/nativescript-angular/commit/354074d)), closes [#799](https://github.com/NativeScript/nativescript-angular/issues/799) + +### Features + +* **Modal:** allow modal to be lazily loaded from a module on demand ([#772](https://github.com/NativeScript/nativescript-angular/issues/772)) ([6a1f6a9](https://github.com/NativeScript/nativescript-angular/commit/6a1f6a9)) + -# [3.0.0](https://github.com/NativeScript/nativescript-angular/compare/v1.5.2..v3.0.0) (2017-05-03) +# [3.0.0](https://github.com/NativeScript/nativescript-angular/compare/v1.5.2..3.0.0) (2017-05-03) ### Bug Fixes diff --git a/build/generate-value-accessor-selector.js b/build/generate-value-accessor-selector.js deleted file mode 100644 index ffa189806..000000000 --- a/build/generate-value-accessor-selector.js +++ /dev/null @@ -1,23 +0,0 @@ -// Usage: -// node generate-value-accessor-selector TextField TextView - -function generateValueAccessorSelector(tagNames) { - const tags = []; - tagNames.forEach(tagName => { - tags.push(tagName); // regular tag - tags.push(tagName.charAt(0).toLowerCase() + tagName.slice(1)); // lowercase first char - tags.push(tagName.split(/(?=[A-Z])/).join("-").toLowerCase()); // kebab case - }); - - const selectors = []; - for (const tag of tags) { - for (const directive of ["ngModel", "formControlName"]) { - selectors.push(`${tag}[${directive}]`); - } - } - return selectors.join(", "); -} - -process.argv.shift(); -process.argv.shift(); -console.log(generateValueAccessorSelector(process.argv)); diff --git a/build/prepublish-next.js b/build/prepublish-next.js new file mode 100644 index 000000000..e320c99f8 --- /dev/null +++ b/build/prepublish-next.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node +const fs = require("fs"); +const path = require("path"); + +const getPackageJson = projectDir => { + const packageJsonPath = getPackageJsonPath(projectDir); + return JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); +}; + +const writePackageJson = (content, projectDir) => { + const packageJsonPath = getPackageJsonPath(projectDir); + fs.writeFileSync(packageJsonPath, JSON.stringify(content, null, 2)) +} + +const getPackageJsonPath = projectDir => path.resolve(projectDir, "package.json"); + +const tag = "next"; +const projectDir = "nativescript-angular"; +const packageJson = getPackageJson(projectDir); +const [, , packageVersion = new Date() ] = process.argv; + +packageJson.publishConfig = Object.assign( + packageJson.publishConfig || {}, + { tag } +); + +delete packageJson.private; + +const currentVersion = packageJson.version; +const nextVersion = `${currentVersion}-${packageVersion}`; +const newPackageJson = Object.assign(packageJson, { version: nextVersion }); + +writePackageJson(newPackageJson, projectDir); diff --git a/build/travis-scripts/add-publishConfig.js b/build/travis-scripts/add-publishConfig.js deleted file mode 100644 index 224c66165..000000000 --- a/build/travis-scripts/add-publishConfig.js +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env node - -var fsModule = require('fs'); - -//Adds a publishConfig section to the package.json file -// and sets a tag to it - -var path = './package.json'; -var fileOptions = {encoding: "utf-8"}; -var content = fsModule.readFileSync(path, fileOptions); - -var tag = process.argv[2]; -if (!tag) { - console.log('Please pass the tag name as an argument!'); - process.exit(1); -} - -var packageDef = JSON.parse(content); -if (!packageDef.publishConfig) { - packageDef.publishConfig = {}; -} -packageDef.publishConfig.tag = tag; - -if (packageDef.private) { - delete packageDef.private; -} - -// adding date and travis build number (2016-07-18-765) to version in order to get unique version for @next build -var package_version = process.argv[3]; -packageDef.version += '-' + package_version; - -var newContent = JSON.stringify(packageDef, null, ' '); -fsModule.writeFileSync(path, newContent, fileOptions); diff --git a/nativescript-angular/CHANGELOG.md b/nativescript-angular/CHANGELOG.md new file mode 100644 index 000000000..873d9cfda --- /dev/null +++ b/nativescript-angular/CHANGELOG.md @@ -0,0 +1,25 @@ + +## [3.1.2](https://github.com/NativeScript/nativescript-angular/compare/3.0.0...3.1.2) (2017-07-12) + + +### Bug Fixes + +* **animations:** use parsers from core modules ([#844](https://github.com/NativeScript/nativescript-angular/issues/844)) ([1abebb6](https://github.com/NativeScript/nativescript-angular/commit/1abebb6)), closes [#738](https://github.com/NativeScript/nativescript-angular/issues/738) +* **dom-adapter:** add fake implementation for getUserAgent ([#835](https://github.com/NativeScript/nativescript-angular/issues/835)) ([743131c](https://github.com/NativeScript/nativescript-angular/commit/743131c)), closes [#831](https://github.com/NativeScript/nativescript-angular/issues/831) +* **forms:** add (touch) event and [disabled] property for controls ([#836](https://github.com/NativeScript/nativescript-angular/issues/836)) ([c8a6404](https://github.com/NativeScript/nativescript-angular/commit/c8a6404)), closes [#804](https://github.com/NativeScript/nativescript-angular/issues/804) +* **forms:** add directives for formControl ([#861](https://github.com/NativeScript/nativescript-angular/issues/861)) ([bd38745](https://github.com/NativeScript/nativescript-angular/commit/bd38745)) +* **ns-router-link:** convert clearHistory string to boolean ([#834](https://github.com/NativeScript/nativescript-angular/issues/834)) ([ff99984](https://github.com/NativeScript/nativescript-angular/commit/ff99984)), closes [#832](https://github.com/NativeScript/nativescript-angular/issues/832) +* **renderer:** add styles when ViewEncapsulation is None ([#812](https://github.com/NativeScript/nativescript-angular/issues/812)) ([8d013e2](https://github.com/NativeScript/nativescript-angular/commit/8d013e2)), closes [#794](https://github.com/NativeScript/nativescript-angular/issues/794) +* **renderer:** attach `CommentNode`s to visual tree ([#888](https://github.com/NativeScript/nativescript-angular/issues/888)) ([65359fa](https://github.com/NativeScript/nativescript-angular/commit/65359fa)), closes [#872](https://github.com/NativeScript/nativescript-angular/issues/872) +* **renderer:** set templateParent to comment and text nodes ([#785](https://github.com/NativeScript/nativescript-angular/issues/785)) ([b127ba7](https://github.com/NativeScript/nativescript-angular/commit/b127ba7)), closes [#777](https://github.com/NativeScript/nativescript-angular/issues/777) [#787](https://github.com/NativeScript/nativescript-angular/issues/787) +* **renderer:** stop performing value conversions ([#806](https://github.com/NativeScript/nativescript-angular/issues/806)) ([354074d](https://github.com/NativeScript/nativescript-angular/commit/354074d)), closes [#799](https://github.com/NativeScript/nativescript-angular/issues/799) +* **time-value-accessor:** typo onTouch -> onTouched ([#843](https://github.com/NativeScript/nativescript-angular/issues/843)) ([6168ddb](https://github.com/NativeScript/nativescript-angular/commit/6168ddb)) +* export NgView and NgElement from element-registry ([#823](https://github.com/NativeScript/nativescript-angular/issues/823)) ([4521c7c](https://github.com/NativeScript/nativescript-angular/commit/4521c7c)) + + +### Features + +* **Modal:** allow modal to be lazily loaded from a module on demand ([#772](https://github.com/NativeScript/nativescript-angular/issues/772)) ([6a1f6a9](https://github.com/NativeScript/nativescript-angular/commit/6a1f6a9)) + + + diff --git a/nativescript-angular/animations/animation-engine.ts b/nativescript-angular/animations/animation-engine.ts index 0dcbd51ff..b5e0911dc 100644 --- a/nativescript-angular/animations/animation-engine.ts +++ b/nativescript-angular/animations/animation-engine.ts @@ -1,3 +1,4 @@ +/* tslint:disable */ import { ɵDomAnimationEngine as DomAnimationEngine } from "@angular/animations/browser"; import { AnimationEvent, AnimationPlayer } from "@angular/animations"; diff --git a/nativescript-angular/directives/list-view-comp.ts b/nativescript-angular/directives/list-view-comp.ts index cbf9aa46f..f2237df90 100644 --- a/nativescript-angular/directives/list-view-comp.ts +++ b/nativescript-angular/directives/list-view-comp.ts @@ -21,11 +21,11 @@ import { } from "@angular/core"; 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 { ObservableArray } from "tns-core-modules/data/observable-array"; import { profile } from "tns-core-modules/profiling"; -import { CommentNode } from "../element-registry"; +import { getSingleViewRecursive } from "../element-registry"; import { isListLikeIterable } from "../collection-facade"; import { listViewLog, listViewError } from "../trace"; @@ -216,30 +216,6 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit { } } -function getSingleViewRecursive(nodes: Array, nestLevel: number): View { - 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}`); - } else if (actualNodes.length > 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 { rootNodes: Array; destroy(): void; diff --git a/nativescript-angular/directives/tab-view.ts b/nativescript-angular/directives/tab-view.ts index 3b578be54..a945531f9 100644 --- a/nativescript-angular/directives/tab-view.ts +++ b/nativescript-angular/directives/tab-view.ts @@ -9,7 +9,7 @@ import { } from "@angular/core"; import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view"; -import { CommentNode } from "../element-registry"; +import { InvisibleNode } from "../element-registry"; import { rendererLog } from "../trace"; import { isBlank } from "../lang-facade"; @@ -105,7 +105,7 @@ export class TabViewItemDirective implements OnInit { const viewRef = this.viewContainer.createEmbeddedView(this.templateRef); // Filter out text nodes and comments const realViews = viewRef.rootNodes.filter(node => - !(node instanceof CommentNode)); + !(node instanceof InvisibleNode)); if (realViews.length > 0) { this.item.view = realViews[0]; diff --git a/nativescript-angular/element-registry.ts b/nativescript-angular/element-registry.ts index 6cf0c6cf0..9a0f044aa 100644 --- a/nativescript-angular/element-registry.ts +++ b/nativescript-angular/element-registry.ts @@ -1,7 +1,8 @@ import { View } from "tns-core-modules/ui/core/view"; +import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; export type NgView = (View & ViewExtensions); -export type NgElement = NgView | CommentNode; +export type NgElement = NgView | InvisibleNode; export interface ViewExtensions { nodeType: number; @@ -15,12 +16,55 @@ export interface ViewClass { new (): View; } -// used for creating comments and text nodes in the renderer -export class CommentNode { - meta: { skipAddToDom: true }; +export abstract class InvisibleNode extends View implements ViewExtensions { + meta: { skipAddToDom: boolean }; templateParent: NgView; + nodeType: number; + nodeName: string; + ngCssClasses: Map; + + constructor() { + super(); + + this.nodeType = 1; + this.nodeName = getClassName(this); + } + + toString() { + return `${this.nodeName}(${this.id})`; + } +} + +export class CommentNode extends InvisibleNode { + protected static id = 0; + + constructor() { + super(); + + this.meta = { + skipAddToDom: false, + }; + this.id = CommentNode.id.toString(); + CommentNode.id += 1; + } +} + +export class TextNode extends InvisibleNode { + protected static id = 0; + + constructor() { + super(); + + this.meta = { + skipAddToDom: true, + }; + this.id = TextNode.id.toString(); + TextNode.id += 1; + } } +const getClassName = instance => instance.constructor.name; + export interface ViewClassMeta { skipAddToDom?: boolean; insertChild?: (parent: NgView, child: NgView, atIndex: number) => void; @@ -76,6 +120,30 @@ export function isKnownView(elementName: string): boolean { elementMap.has(elementName.toLowerCase()); } +export function getSingleViewRecursive(nodes: Array, nestLevel: number): View { + const actualNodes = nodes.filter(node => !(node instanceof InvisibleNode)); + + if (actualNodes.length === 0) { + 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}`); + } + + const rootLayout = actualNodes[0]; + if (!rootLayout) { + return getSingleViewRecursive(rootLayout.children, nestLevel + 1); + } + + const parentLayout = rootLayout.parent; + if (parentLayout instanceof LayoutBase) { + parentLayout.removeChild(rootLayout); + } + + return rootLayout; +} + // Register default NativeScript components // Note: ActionBar related components are registerd together with action-bar directives. registerElement("AbsoluteLayout", () => require("tns-core-modules/ui/layouts/absolute-layout").AbsoluteLayout); diff --git a/nativescript-angular/package.json b/nativescript-angular/package.json index f08150dcb..0ec2d8c69 100644 --- a/nativescript-angular/package.json +++ b/nativescript-angular/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "nativescript-angular", - "version": "3.1.0", + "version": "3.1.2", "description": "An Angular renderer that lets you build mobile apps with NativeScript.", "homepage": "https://www.nativescript.org/", "bugs": "https://github.com/NativeScript/nativescript-angular/issues", @@ -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", + "tns-core-modules": "^3.1.0 || >3.2.0-", "zone.js": "^0.8.4" }, "devDependencies": { @@ -64,11 +64,11 @@ "@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", + "codelyzer": "^3.1.2", + "rxjs": "^5.4.2", "tns-core-modules": "next", "tslint": "^5.1.0", - "typescript": "^2.3.2", + "typescript": "^2.4.0", "zone.js": "^0.8.4" } } diff --git a/nativescript-angular/renderer.ts b/nativescript-angular/renderer.ts index b95318bc3..8f3826e2d 100644 --- a/nativescript-angular/renderer.ts +++ b/nativescript-angular/renderer.ts @@ -13,7 +13,7 @@ import { profile } from "tns-core-modules/profiling"; import { APP_ROOT_VIEW, DEVICE, getRootPage } from "./platform-providers"; import { isBlank } from "./lang-facade"; import { ViewUtil } from "./view-util"; -import { NgView, CommentNode } from "./element-registry"; +import { NgView, InvisibleNode } from "./element-registry"; import { rendererLog as traceLog } from "./trace"; // CONTENT_ATTR not exported from NativeScript_renderer - we need it for styles application. @@ -120,7 +120,7 @@ export class NativeScriptRenderer extends Renderer2 { } @profile - createComment(_value: any): CommentNode { + createComment(_value: any): InvisibleNode { traceLog(`NativeScriptRenderer.createComment ${_value}`); return this.viewUtil.createComment(); } @@ -132,7 +132,7 @@ export class NativeScriptRenderer extends Renderer2 { } @profile - createText(_value: string): CommentNode { + createText(_value: string): InvisibleNode { traceLog(`NativeScriptRenderer.createText ${_value}`); return this.viewUtil.createText(); } @@ -284,6 +284,7 @@ class EmulatedRenderer extends NativeScriptRenderer { } } +// tslint:disable-next-line const addStyleToCss = profile('"renderer".addStyleToCss', function addStyleToCss(style: string): void { addCss(style); }); diff --git a/nativescript-angular/router/ns-module-factory-loader.ts b/nativescript-angular/router/ns-module-factory-loader.ts index a64868808..052669d87 100644 --- a/nativescript-angular/router/ns-module-factory-loader.ts +++ b/nativescript-angular/router/ns-module-factory-loader.ts @@ -6,7 +6,10 @@ import { SystemJsNgModuleLoader, Type, } from "@angular/core"; -import { path, knownFolders } from "tns-core-modules/file-system"; +import { + path as fileSystemPath, + knownFolders +} from "tns-core-modules/file-system"; const SEPARATOR = "#"; @@ -51,9 +54,9 @@ function splitPath(path: string): {modulePath: string, exportName: string} { function getAbsolutePath(relativePath: string) { const projectPath = knownFolders.currentApp().path; - const absolutePath = path.join(projectPath, relativePath); + const absolutePath = fileSystemPath.join(projectPath, relativePath); - return path.normalize(absolutePath); + return fileSystemPath.normalize(absolutePath); } function checkNotEmpty(value: any, modulePath: string, exportName: string): void { diff --git a/nativescript-angular/router/ns-router-link.ts b/nativescript-angular/router/ns-router-link.ts index 1881f43e3..0a5bfed50 100644 --- a/nativescript-angular/router/ns-router-link.ts +++ b/nativescript-angular/router/ns-router-link.ts @@ -107,7 +107,7 @@ export class NSRouterLink implements OnChanges { // tslint:disable-line:directiv } else { return { animated: true, - transition: this.pageTransition + transition: this.pageTransition }; } } diff --git a/nativescript-angular/tsconfig.json b/nativescript-angular/tsconfig.json index 641cfd5e2..e05ddfed9 100644 --- a/nativescript-angular/tsconfig.json +++ b/nativescript-angular/tsconfig.json @@ -11,8 +11,6 @@ "declaration": true, "removeComments": false, "noEmitOnError": true, - "noUnusedLocals": true, - "noUnusedParameters": true, "noImplicitAny": false, "lib": [ "dom", diff --git a/nativescript-angular/tslint.json b/nativescript-angular/tslint.json index 4a49adfe4..b9630d813 100644 --- a/nativescript-angular/tslint.json +++ b/nativescript-angular/tslint.json @@ -61,6 +61,7 @@ "no-string-literal": false, "no-switch-case-fall-through": true, "no-unused-expression": true, + "no-unused-variable": true, "no-var-keyword": true, "radix": false, "switch-default": true, diff --git a/nativescript-angular/value-accessors/base-value-accessor.ts b/nativescript-angular/value-accessors/base-value-accessor.ts index d7b180c56..25ac8aa7a 100644 --- a/nativescript-angular/value-accessors/base-value-accessor.ts +++ b/nativescript-angular/value-accessors/base-value-accessor.ts @@ -2,7 +2,7 @@ import { ControlValueAccessor } from "@angular/forms"; import { View } from "tns-core-modules/ui/core/view"; export class BaseValueAccessor implements ControlValueAccessor { - private pendingChangeNotification: number = 0; + private pendingChangeNotification: any = 0; onChange = (_) => { }; onTouched = () => {}; diff --git a/nativescript-angular/value-accessors/checked-value-accessor.ts b/nativescript-angular/value-accessors/checked-value-accessor.ts index 85d8a1a2c..af1a22289 100644 --- a/nativescript-angular/value-accessors/checked-value-accessor.ts +++ b/nativescript-angular/value-accessors/checked-value-accessor.ts @@ -20,8 +20,8 @@ const CHECKED_VALUE_ACCESSOR = { */ @Directive({ selector: - "Switch[ngModel],Switch[formControlName]," + - "switch[ngModel],switch[formControlName]", + "Switch[ngModel],Switch[formControlName],Switch[formControl]," + + "switch[ngModel],switch[formControlName],switch[formControl]", providers: [CHECKED_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/value-accessors/date-value-accessor.ts b/nativescript-angular/value-accessors/date-value-accessor.ts index 4541f9bb9..9e66bbc92 100644 --- a/nativescript-angular/value-accessors/date-value-accessor.ts +++ b/nativescript-angular/value-accessors/date-value-accessor.ts @@ -19,10 +19,10 @@ const DATE_VALUE_ACCESSOR = { * ``` */ @Directive({ - selector: "DatePicker[ngModel],DatePicker[formControlName]," + - "datepicker[ngModel],datepicker[formControlName]," + - "datePicker[ngModel],datePicker[formControlName]," + - "date-picker[ngModel],date-picker[formControlName]", + selector: "DatePicker[ngModel],DatePicker[formControlName],DatePicker[formControl]," + + "datepicker[ngModel],datepicker[formControlName],datepicker[formControl]," + + "datePicker[ngModel],datePicker[formControlName],datePicker[formControl]," + + "date-picker[ngModel],date-picker[formControlName],date-picker[formControl]", providers: [DATE_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/value-accessors/number-value-accessor.ts b/nativescript-angular/value-accessors/number-value-accessor.ts index 224a9790a..44451f96e 100644 --- a/nativescript-angular/value-accessors/number-value-accessor.ts +++ b/nativescript-angular/value-accessors/number-value-accessor.ts @@ -20,8 +20,8 @@ const NUMBER_VALUE_ACCESSOR = { */ @Directive({ selector: - "Slider[ngModel],Slider[formControlName]," + - "slider[ngModel],slider[formControlName]", + "Slider[ngModel],Slider[formControlName],Slider[formControl]," + + "slider[ngModel],slider[formControlName],slider[formControl]", providers: [NUMBER_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts b/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts index 462d294dc..005a40f98 100644 --- a/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts +++ b/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts @@ -22,20 +22,20 @@ export type SelectableView = {selectedIndex: number} & View; */ @Directive({ selector: - "SegmentedBar[ngModel],SegmentedBar[formControlName]," + - "segmentedBar[ngModel],segmentedBar[formControlName]," + - "segmentedbar[ngModel],segmentedbar[formControlName]," + - "segmented-bar[ngModel],segmented-bar[formControlName]," + + "SegmentedBar[ngModel],SegmentedBar[formControlName],SegmentedBar[formControl]," + + "segmentedBar[ngModel],segmentedBar[formControlName],segmentedBar[formControl]," + + "segmentedbar[ngModel],segmentedbar[formControlName],segmentedbar[formControl]," + + "segmented-bar[ngModel],segmented-bar[formControlName],segmented-bar[formControl]," + - "ListPicker[ngModel],ListPicker[formControlName]," + - "listPicker[ngModel],listPicker[formControlName]," + - "listpicker[ngModel],listpicker[formControlName]," + - "list-picker[ngModel],list-picker[formControlName]," + + "ListPicker[ngModel],ListPicker[formControlName],ListPicker[formControl]," + + "listPicker[ngModel],listPicker[formControlName],listPicker[formControl]," + + "listpicker[ngModel],listpicker[formControlName],listpicker[formControl]," + + "list-picker[ngModel],list-picker[formControlName],list-picker[formControl]," + - "TabView[ngModel],TabView[formControlName]," + - "tabView[ngModel],tabView[formControlName]," + - "tabview[ngModel],tabview[formControlName]," + - "tab-view[ngModel],tab-view[formControlName]", + "TabView[ngModel],TabView[formControlName],TabView[formControl]," + + "tabView[ngModel],tabView[formControlName],tabView[formControl]," + + "tabview[ngModel],tabview[formControlName],tabview[formControl]," + + "tab-view[ngModel],tab-view[formControlName],tab-view[formControl]", providers: [SELECTED_INDEX_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/value-accessors/text-value-accessor.ts b/nativescript-angular/value-accessors/text-value-accessor.ts index 03688b27e..b578cf6a3 100644 --- a/nativescript-angular/value-accessors/text-value-accessor.ts +++ b/nativescript-angular/value-accessors/text-value-accessor.ts @@ -22,20 +22,20 @@ export type TextView = {text: string} & View; */ @Directive({ selector: - "TextField[ngModel],TextField[formControlName]," + - "textField[ngModel],textField[formControlName]," + - "textfield[ngModel],textfield[formControlName]," + - "text-field[ngModel],text-field[formControlName]," + + "TextField[ngModel],TextField[formControlName],TextField[formControl]," + + "textField[ngModel],textField[formControlName],textField[formControl]," + + "textfield[ngModel],textfield[formControlName],textfield[formControl]," + + "text-field[ngModel],text-field[formControlName],text-field[formControl]," + - "TextView[ngModel],TextView[formControlName]," + - "textView[ngModel],textView[formControlName]," + - "textview[ngModel],textview[formControlName]," + - "text-view[ngModel],text-view[formControlName]," + + "TextView[ngModel],TextView[formControlName],TextView[formControl]," + + "textView[ngModel],textView[formControlName],textView[formControl]," + + "textview[ngModel],textview[formControlName],textview[formControl]," + + "text-view[ngModel],text-view[formControlName],text-view[formControl]," + - "SearchBar[ngModel],SearchBar[formControlName]," + - "searchBar[ngModel],searchBar[formControlName]," + - "searchbar[ngModel],searchbar[formControlName]," + - "search-bar[ngModel], search-bar[formControlName]", + "SearchBar[ngModel],SearchBar[formControlName],SearchBar[formControl]," + + "searchBar[ngModel],searchBar[formControlName],searchBar[formControl]," + + "searchbar[ngModel],searchbar[formControlName],searchbar[formControl]," + + "search-bar[ngModel], search-bar[formControlName],search-bar[formControl]", providers: [TEXT_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/value-accessors/time-value-accessor.ts b/nativescript-angular/value-accessors/time-value-accessor.ts index 4112de8f0..d62b170e7 100644 --- a/nativescript-angular/value-accessors/time-value-accessor.ts +++ b/nativescript-angular/value-accessors/time-value-accessor.ts @@ -20,10 +20,10 @@ const TIME_VALUE_ACCESSOR = { */ @Directive({ selector: - "TimePicker[ngModel],TimePicker[formControlName]," + - "timepicker[ngModel],timepicker[formControlName]," + - "timePicker[ngModel],timePicker[formControlName]," + - "time-picker[ngModel], time-picker[formControlName]", + "TimePicker[ngModel],TimePicker[formControlName],TimePicker[formControl]," + + "timepicker[ngModel],timepicker[formControlName],timepicker[formControl]," + + "timePicker[ngModel],timePicker[formControlName],timePicker[formControl]," + + "time-picker[ngModel],time-picker[formControlName],time-picker[formControl]", providers: [TIME_VALUE_ACCESSOR], host: { "(touch)": "onTouched()", diff --git a/nativescript-angular/view-util.ts b/nativescript-angular/view-util.ts index 6349c203f..99b196197 100644 --- a/nativescript-angular/view-util.ts +++ b/nativescript-angular/view-util.ts @@ -5,8 +5,10 @@ import { ContentView } from "tns-core-modules/ui/content-view"; import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; import { CommentNode, + InvisibleNode, NgElement, NgView, + TextNode, ViewExtensions, getViewClass, getViewMeta, @@ -52,9 +54,8 @@ export class ViewUtil { } public insertChild(parent: any, child: NgElement, atIndex: number = -1) { - if (child instanceof CommentNode) { + if (child instanceof InvisibleNode) { child.templateParent = parent; - return; } if (!parent || isDetachedElement(child)) { @@ -79,16 +80,11 @@ export class ViewUtil { parent.content = child; } else if (parent && parent._addChildFromBuilder) { parent._addChildFromBuilder(child.nodeName, child); - } else { - // throw new Error("Parent can"t contain children: " + parent.nodeName + ", " + parent); } } public removeChild(parent: any, child: NgElement) { - if (!parent || - child instanceof CommentNode || - isDetachedElement(child)) { - + if (!parent || isDetachedElement(child)) { return; } @@ -102,8 +98,6 @@ export class ViewUtil { } } else if (isView(parent)) { parent._removeView(child); - } else { - // throw new Error("Unknown parent type: " + parent); } } @@ -112,17 +106,15 @@ export class ViewUtil { return parent.getChildIndex(child); } else if (isContentView(parent)) { return child === parent.content ? 0 : -1; - } else { - // throw new Error("Parent can"t contain children: " + parent); } } - public createComment(): CommentNode { + public createComment(): InvisibleNode { return new CommentNode(); } - public createText(): CommentNode { - return new CommentNode(); + public createText(): InvisibleNode { + return new TextNode(); } public createView(name: string): NgView { diff --git a/tests/app/App_Resources/Android/app.gradle b/tests/app/App_Resources/Android/app.gradle new file mode 100644 index 000000000..5a83b0360 --- /dev/null +++ b/tests/app/App_Resources/Android/app.gradle @@ -0,0 +1,23 @@ +// Add your native dependencies here: + +// Uncomment to add recyclerview-v7 dependency +//dependencies { +// compile 'com.android.support:recyclerview-v7:+' +//} + +android { + defaultConfig { + generatedDensities = [] + applicationId = "org.nativescript.tests" + + //override supported platforms + // ndk { + // abiFilters.clear() + // abiFilters "armeabi-v7a" + // } + + } + aaptOptions { + additionalParameters "--no-version-vectors" + } +} diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index fecbaf982..6efc463c8 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -94,6 +94,39 @@ export class NgIfLabel { } } +@Component({ + selector: "ng-if-two-elements", + template: ` + + + + + ` +}) +export class NgIfTwoElements { + public show: boolean = false; + constructor(public elementRef: ElementRef) { + } +} + +@Component({ + selector: "ng-if-multiple", + template: ` + + + + + + + + ` +}) +export class NgIfMultiple { + public show: boolean = false; + constructor(public elementRef: ElementRef) { + } +} + @Component({ selector: "ng-if-else", template: ` @@ -154,7 +187,9 @@ describe("Renderer E2E", () => { LayoutWithLabel, LabelCmp, LabelContainer, ProjectableCmp, ProjectionContainer, StyledLabelCmp, StyledLabelCmp2, - NgIfLabel, NgIfElseComponent, NgIfThenElseComponent, + NgIfLabel, NgIfThenElseComponent, NgIfMultiple, + NgIfTwoElements, NgIfMultiple, + NgIfElseComponent, NgIfThenElseComponent, NgForLabel, ]).then((app) => { testApp = app; @@ -256,7 +291,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)", dumpView(componentRoot)); + assert.equal("(ProxyViewContainer (CommentNode))", dumpView(componentRoot)); }); }); @@ -267,7 +302,43 @@ describe("Renderer E2E", () => { component.show = true; testApp.appRef.tick(); - assert.equal("(ProxyViewContainer (Label))", dumpView(componentRoot)); + assert.equal("(ProxyViewContainer (CommentNode), (Label))", dumpView(componentRoot)); + }); + }); + + it("ngIf shows elements in correct order when two are rendered", () => { + return testApp.loadComponent(NgIfTwoElements).then((componentRef) => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + component.show = true; + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer (StackLayout (CommentNode), (Label), (Button)))", + dumpView(componentRoot)); + }); + }); + + + it("ngIf shows elements in correct order when multiple are rendered and there's *ngIf", () => { + return testApp.loadComponent(NgIfMultiple).then((componentRef) => { + const component = componentRef.instance; + const componentRoot = component.elementRef.nativeElement; + + component.show = true; + testApp.appRef.tick(); + assert.equal( + "(ProxyViewContainer " + + "(StackLayout " + + "(Label[text=1]), " + + "(Label[text=2]), " + + "(Label[text=3]), " + + "(CommentNode), " + // ng-reflect comment + "(Label[text=4]), " + // the content to be displayed and its anchor + "(Label[text=5])" + + ")" + + ")", + dumpView(componentRoot, true)); }); }); @@ -280,7 +351,8 @@ describe("Renderer E2E", () => { assert.equal( "(ProxyViewContainer " + "(StackLayout " + - "(Label[text=If])))", // the content to be displayed + "(CommentNode), " + // ng-reflect comment + "(Label[text=If]), (CommentNode)))", // the content to be displayed and its anchor dumpView(componentRoot, true)); }); @@ -296,7 +368,8 @@ describe("Renderer E2E", () => { assert.equal( "(ProxyViewContainer " + "(StackLayout " + - "(Label[text=Else])))", // the content to be displayed + "(CommentNode), " + // ng-reflect comment + "(Label[text=Else]), (CommentNode)))", // the content to be displayed and its anchor dumpView(componentRoot, true)); }); @@ -311,7 +384,10 @@ describe("Renderer E2E", () => { assert.equal( "(ProxyViewContainer " + "(StackLayout " + - "(Label[text=Then])))", // the content to be displayed + "(CommentNode), " + // ng-reflect comment + "(Label[text=Then]), (CommentNode), " + // the content to be displayed and its anchor + "(CommentNode)))", // the anchor for the else template + dumpView(componentRoot, true)); }); }); @@ -327,7 +403,9 @@ describe("Renderer E2E", () => { assert.equal( "(ProxyViewContainer " + "(StackLayout " + - "(Label[text=Else])))", // the content to be displayed + "(CommentNode), " + // the content to be displayed + "(Label[text=Else]), (CommentNode), " + // the content to be displayed + "(CommentNode)))", // the content to be displayed dumpView(componentRoot, true)); }); @@ -337,7 +415,7 @@ describe("Renderer E2E", () => { return testApp.loadComponent(NgForLabel).then((componentRef) => { const componentRoot = componentRef.instance.elementRef.nativeElement; assert.equal( - "(ProxyViewContainer (Label[text=one]), (Label[text=two]), (Label[text=three]))", + "(ProxyViewContainer (CommentNode), (Label[text=one]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true)); }); }); @@ -351,7 +429,7 @@ describe("Renderer E2E", () => { testApp.appRef.tick(); assert.equal( - "(ProxyViewContainer (Label[text=one]), (Label[text=three]))", + "(ProxyViewContainer (CommentNode), (Label[text=one]), (Label[text=three]))", dumpView(componentRoot, true)); }); }); @@ -365,7 +443,7 @@ describe("Renderer E2E", () => { testApp.appRef.tick(); assert.equal( - "(ProxyViewContainer " + + "(ProxyViewContainer (CommentNode), " + "(Label[text=one]), (Label[text=new]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true)); }); @@ -464,19 +542,5 @@ describe("Renderer attach/detach", () => { assert.equal(parent.getChildrenCount(), 0); assert.isUndefined(button.parent); }); - - it("attaching and detaching comment anchor to content view does not affect its content", () => { - const parent = renderer.createElement("ContentView"); - const button =