diff --git a/.eslintrc.json b/.eslintrc.json index 4755c00..0df28d9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,18 +12,13 @@ "files": ["*.ts", "*.tsx"], "extends": ["plugin:@nx/typescript"], "rules": { - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/no-extra-semi": "error", - "no-extra-semi": "off" + "@typescript-eslint/no-inferrable-types": "off" } }, { "files": ["*.js", "*.jsx"], "extends": ["plugin:@nx/javascript"], - "rules": { - "@typescript-eslint/no-extra-semi": "error", - "no-extra-semi": "off" - } + "rules": {} } ] } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a243ac4..75925e6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,11 +23,8 @@ jobs: - uses: actions/setup-node@v3 with: node-version: lts/* - cache: 'yarn' - uses: nrwl/nx-set-shas@v3 - - name: Setup global dependencies - run: npm i -g yarn - - name: yarn install - run: yarn + - name: npm install + run: npm install --legacy-peer-deps - name: Build.all affected - run: yarn nx affected --target=build --exclude nativescript-demo-ng + run: npx nx affected --target=build --exclude nativescript-demo-ng diff --git a/.gitignore b/.gitignore index 2fb1056..e8cabb7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,8 @@ # dependencies /node_modules /packages/*/node_modules -package-lock.json .npmrc +yarn.lock # IDEs and editors /.idea @@ -48,4 +48,6 @@ Thumbs.db /.env .nx/cache -.nx/workspace-data \ No newline at end of file +.nx/workspace-data +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md diff --git a/.husky/pre-commit b/.husky/pre-commit index 4ebab2a..4b60b64 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - npx lint-staged --allow-empty --relative diff --git a/.prettierignore b/.prettierignore index 4ccb9a2..50732da 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,7 @@ /dist /coverage +packages/angular/dist **/xplat/*/.xplatframework diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..55712c1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6096e44..39ea524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +# [21.0.0](https://github.com/NativeScript/angular/compare/20.1.1...21.0.0) (2026-01-04) + + +### Features + +* Angular 21 ([#157](https://github.com/NativeScript/angular/issues/157)) ([1cc0a89](https://github.com/NativeScript/angular/commit/1cc0a89dcf5f3239fac566a20ee865baf38129bf)) + + + +## [20.1.1](https://github.com/NativeScript/angular/compare/20.1.0...20.1.1) (2026-01-04) + + +### Features + +* SplitView support ([#160](https://github.com/NativeScript/angular/issues/160)) ([280b388](https://github.com/NativeScript/angular/commit/280b388feb30c80411afcc03684bb0f567b5d8af)) + + + +# [20.1.0](https://github.com/NativeScript/angular/compare/20.0.0...20.1.0) (2025-12-02) + + +### Features + +* **ListView:** sticky headers, search bar and sectioned data support with v9 ([5ad8a89](https://github.com/NativeScript/angular/commit/5ad8a897a05014d0c737f7f8580f156574938df0)) + * **Note**: Requires NativeScript Core v9+ + + + +# [20.0.0](https://github.com/NativeScript/angular/compare/19.0.1...20.0.0) (2025-06-01) + + +### Features + +* Angular 20 ([#151](https://github.com/NativeScript/angular/issues/151)) ([62d9fb5](https://github.com/NativeScript/angular/commit/62d9fb5329efb28b5d595f11bf8732ae56a878f7)) + + + ## [19.0.1](https://github.com/NativeScript/angular/compare/19.0.0...19.0.1) (2025-01-29) diff --git a/DevelopmentWorkflow.md b/DevelopmentWorkflow.md index 1755ec1..b2f7064 100644 --- a/DevelopmentWorkflow.md +++ b/DevelopmentWorkflow.md @@ -33,7 +33,7 @@ $ cd angular ``` $ cd angular -$ yarn clean.all +$ npm run clean.all ``` ### Run some of the e2e applications e.g. router-tab-view @@ -43,7 +43,7 @@ $ yarn clean.all Install NPM packages (use the local copy of `@nativescript/angular`): ``` $ cd e2e/router-tab-view -$ yarn install +$ npm install ``` Start the app: diff --git a/apps/nativescript-demo-ng/App_Resources/Android/app.gradle b/apps/nativescript-demo-ng/App_Resources/Android/app.gradle index f995ed2..391032a 100644 --- a/apps/nativescript-demo-ng/App_Resources/Android/app.gradle +++ b/apps/nativescript-demo-ng/App_Resources/Android/app.gradle @@ -6,9 +6,10 @@ //} android { + namespace "org.nativescript.demong" defaultConfig { - minSdkVersion 17 - targetSdkVersion 29 + minSdkVersion 24 + targetSdkVersion 34 generatedDensities = [] applicationId = "org.nativescript.demong" manifestPlaceholders = [isUnitTesting:"${unitTesting}"] diff --git a/apps/nativescript-demo-ng/App_Resources/Android/src/main/AndroidManifest.xml b/apps/nativescript-demo-ng/App_Resources/Android/src/main/AndroidManifest.xml index f82cfbe..896af51 100644 --- a/apps/nativescript-demo-ng/App_Resources/Android/src/main/AndroidManifest.xml +++ b/apps/nativescript-demo-ng/App_Resources/Android/src/main/AndroidManifest.xml @@ -20,13 +20,15 @@ android:icon="@drawable/icon" android:usesCleartextTraffic="${isUnitTesting}" android:label="@string/app_name" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + android:networkSecurityConfig="@xml/network_security_config"> + android:theme="@style/LaunchScreenTheme" + android:exported="true"> diff --git a/apps/nativescript-demo-ng/App_Resources/Android/src/main/res/xml/network_security_config.xml b/apps/nativescript-demo-ng/App_Resources/Android/src/main/res/xml/network_security_config.xml new file mode 100644 index 0000000..dd320be --- /dev/null +++ b/apps/nativescript-demo-ng/App_Resources/Android/src/main/res/xml/network_security_config.xml @@ -0,0 +1,16 @@ + + + + + + + + + + localhost + 127.0.0.1 + 10.0.2.2 + + + + diff --git a/apps/nativescript-demo-ng/App_Resources/iOS/Info.plist b/apps/nativescript-demo-ng/App_Resources/iOS/Info.plist index 3c0d86f..3fa7c4e 100644 --- a/apps/nativescript-demo-ng/App_Resources/iOS/Info.plist +++ b/apps/nativescript-demo-ng/App_Resources/iOS/Info.plist @@ -1,58 +1,58 @@ - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiresFullScreen - - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - ITSAppUsesNonExemptEncryption - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsArbitraryLoadsForMedia + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS - NSAllowsArbitraryLoadsInWebContent + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + ITSAppUsesNonExemptEncryption + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsForMedia + + NSAllowsArbitraryLoadsInWebContent + + - diff --git a/apps/nativescript-demo-ng/package.json b/apps/nativescript-demo-ng/package.json index 2dc6992..833af55 100644 --- a/apps/nativescript-demo-ng/package.json +++ b/apps/nativescript-demo-ng/package.json @@ -6,10 +6,10 @@ "@nativescript/core": "file:../../node_modules/@nativescript/core" }, "devDependencies": { - "@nativescript/android": "~8.8.0", - "@nativescript/ios": "~8.8.0", + "@nativescript/android": "~9.0.0", + "@nativescript/ios": "~9.0.0", "@nativescript/tailwind": "^2.1.0", - "@nativescript/unit-test-runner": "^3.0.1", - "@nativescript/visionos": "8.8.1" + "@nativescript/unit-test-runner": "^4.0.0", + "@nativescript/visionos": "~9.0.0" } } diff --git a/apps/nativescript-demo-ng/project.json b/apps/nativescript-demo-ng/project.json index c3946f4..3149158 100644 --- a/apps/nativescript-demo-ng/project.json +++ b/apps/nativescript-demo-ng/project.json @@ -40,7 +40,9 @@ "forDevice": false, "prepare": false }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "clean": { "executor": "@nativescript/nx:clean", @@ -51,11 +53,16 @@ }, "test": { "executor": "@nativescript/nx:test", - "outputs": ["{workspaceRoot}/coverage/apps/nativescript-demo-ng"], + "outputs": [ + "{workspaceRoot}/coverage/apps/nativescript-demo-ng" + ], "options": { "coverage": false }, + "dependsOn": [ + "^build" + ], "configurations": {} } } -} +} \ No newline at end of file diff --git a/apps/nativescript-demo-ng/src/app/app.component.ts b/apps/nativescript-demo-ng/src/app/app.component.ts index f789d41..083a43d 100644 --- a/apps/nativescript-demo-ng/src/app/app.component.ts +++ b/apps/nativescript-demo-ng/src/app/app.component.ts @@ -1,16 +1,15 @@ -import { Component, NO_ERRORS_SCHEMA, OnDestroy, OnInit, ViewContainerRef } from '@angular/core'; +import { Component, NO_ERRORS_SCHEMA, OnDestroy, OnInit } from '@angular/core'; import { PageRouterOutlet } from '@nativescript/angular'; // registerElement('ns-app', () => GridLayout); @Component({ selector: 'ns-app', - moduleId: module.id, templateUrl: './app.component.html', imports: [PageRouterOutlet], schemas: [NO_ERRORS_SCHEMA], }) export class AppComponent implements OnInit, OnDestroy { - constructor(private vcRef: ViewContainerRef) {} + ngOnInit() { console.log('ngOnInit'); } diff --git a/apps/nativescript-demo-ng/src/app/app.routes.ts b/apps/nativescript-demo-ng/src/app/app.routes.ts index e80adcb..3099fef 100644 --- a/apps/nativescript-demo-ng/src/app/app.routes.ts +++ b/apps/nativescript-demo-ng/src/app/app.routes.ts @@ -1,6 +1,8 @@ import { Routes } from '@angular/router'; import { ItemDetailComponent } from './item/item-detail.component'; import { ItemsComponent } from './item/items.component'; +import { ListViewStickyComponent } from './list-view-sticky/list-view-sticky.component'; +import { SPLIT_VIEW_ROUTES } from './split-view-demo/split-view.routes'; // import { HomeComponent } from './home/home.component'; // import { BootGuardService } from './boot-guard.service'; @@ -10,6 +12,14 @@ export const routes: Routes = [ { path: 'item/:id', component: ItemDetailComponent }, { path: 'item2', loadChildren: () => import('./item2/item2.routes').then((m) => m.ITEM2_ROUTES) }, { path: 'rootlazy', loadChildren: () => import('./item3/item3.module').then((m) => m.Item3Module) }, + { + path: 'list-view-sticky', + component: ListViewStickyComponent, + }, + { + path: 'split-view-demo', + children: SPLIT_VIEW_ROUTES, + }, /** * Test tab named outlets diff --git a/apps/nativescript-demo-ng/src/app/home/home.component.html b/apps/nativescript-demo-ng/src/app/home/home.component.html index e5e865c..68cc8e7 100644 --- a/apps/nativescript-demo-ng/src/app/home/home.component.html +++ b/apps/nativescript-demo-ng/src/app/home/home.component.html @@ -1,5 +1,5 @@ - + @@ -13,3 +13,46 @@ + + + + \ No newline at end of file diff --git a/apps/nativescript-demo-ng/src/app/home/home.component.ts b/apps/nativescript-demo-ng/src/app/home/home.component.ts index 6d9e70d..3565191 100644 --- a/apps/nativescript-demo-ng/src/app/home/home.component.ts +++ b/apps/nativescript-demo-ng/src/app/home/home.component.ts @@ -1,29 +1,27 @@ -import { Component, NgZone, OnInit } from '@angular/core'; +import { Component, inject, NgZone, NO_ERRORS_SCHEMA, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { RouterExtensions, NativeScriptCommonModule } from '@nativescript/angular'; -import { Page, TabView } from '@nativescript/core'; +import { EventData, Page, TabView } from '@nativescript/core'; @Component({ - moduleId: module.id, selector: 'demo-home', templateUrl: './home.component.html', imports: [NativeScriptCommonModule], - standalone: true, + schemas: [NO_ERRORS_SCHEMA], }) export class HomeComponent implements OnInit { + private _ngZone = inject(NgZone); + // vcRef: ViewContainerRef, + private _activeRoute = inject(ActivatedRoute); + private _page = inject(Page); + private _ngRouter = inject(Router); + private _router = inject(RouterExtensions); tabItems: { [key: string]: { index: number; title?: string; iconSource?: string; textTransform?: string } } = {}; private _tabs = ['start']; private _hasInitTab: { start?: boolean } = {}; private _tabView: TabView; - constructor( - private _ngZone: NgZone, - // vcRef: ViewContainerRef, - private _activeRoute: ActivatedRoute, - private _page: Page, - private _ngRouter: Router, - private _router: RouterExtensions, - ) { + constructor() { this._initMenu(); } @@ -37,10 +35,6 @@ export class HomeComponent implements OnInit { } } - loadedTabView(args) { - // - } - private _viewTab(index: number) { let route; switch (index) { @@ -63,7 +57,7 @@ export class HomeComponent implements OnInit { }); } - private _initMenu(profilePic?: string) { + private _initMenu() { for (let i = 0; i < this._tabs.length; i++) { const tab = this._tabs[i]; // console.log('================') diff --git a/apps/nativescript-demo-ng/src/app/item/item-detail.component.ts b/apps/nativescript-demo-ng/src/app/item/item-detail.component.ts index 23e6585..961475c 100644 --- a/apps/nativescript-demo-ng/src/app/item/item-detail.component.ts +++ b/apps/nativescript-demo-ng/src/app/item/item-detail.component.ts @@ -1,4 +1,4 @@ -import { Component, NO_ERRORS_SCHEMA, OnInit } from '@angular/core'; +import { Component, inject, NO_ERRORS_SCHEMA, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Item } from './item'; @@ -7,19 +7,14 @@ import { NativeScriptCommonModule } from '@nativescript/angular'; @Component({ selector: 'ns-details', - moduleId: module.id, templateUrl: './item-detail.component.html', imports: [NativeScriptCommonModule], - standalone: true, - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }) export class ItemDetailComponent implements OnInit { - item: Item; - - constructor( - private itemService: ItemService, - private route: ActivatedRoute, - ) {} + item: Item | null = null; + private itemService = inject(ItemService); + private route = inject(ActivatedRoute); ngOnInit(): void { const id = +this.route.snapshot.params.id; diff --git a/apps/nativescript-demo-ng/src/app/item/items.component.ts b/apps/nativescript-demo-ng/src/app/item/items.component.ts index cd5972d..00fdd82 100644 --- a/apps/nativescript-demo-ng/src/app/item/items.component.ts +++ b/apps/nativescript-demo-ng/src/app/item/items.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { Component, OnInit, OnDestroy, NO_ERRORS_SCHEMA, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Item } from './item'; @@ -8,22 +8,17 @@ import { ModalDialogService, NativeDialogService, NativeScriptCommonModule } fro @Component({ selector: 'ns-items', - moduleId: module.id, templateUrl: './items.component.html', imports: [NativeScriptCommonModule], - standalone: true, - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }) export class ItemsComponent implements OnInit, OnDestroy { - message = 'Hello Angular 19!'; - items: Array; - - constructor( - private itemService: ItemService, - private nativeDialog: NativeDialogService, - private modalDialog: ModalDialogService, - private http: HttpClient, - ) {} + message = 'Hello Angular 21.0.0!'; + items: Array = []; + private itemService = inject(ItemService); + private nativeDialog = inject(NativeDialogService); + private modalDialog = inject(ModalDialogService); + private http = inject(HttpClient); ngOnInit(): void { console.log('ItemsComponent ngOnInit'); diff --git a/apps/nativescript-demo-ng/src/app/item2/item-detail2.component.html b/apps/nativescript-demo-ng/src/app/item2/item-detail2.component.html index 1346c48..616a490 100644 --- a/apps/nativescript-demo-ng/src/app/item2/item-detail2.component.html +++ b/apps/nativescript-demo-ng/src/app/item2/item-detail2.component.html @@ -14,7 +14,7 @@