From 2b56508d77b7e73b3424a7b3b7e4abca0a9f74a0 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Sat, 4 Jan 2025 12:44:57 -0800 Subject: [PATCH] feat: Angular 19 (#236) --- packages/template-blank-ng/package.json | 30 +++++++++--------- .../src/app/app-routing.module.ts | 17 ---------- .../src/app/app.component.ts | 7 +++-- .../template-blank-ng/src/app/app.module.ts | 13 -------- .../template-blank-ng/src/app/app.routes.ts | 6 ++++ .../src/app/home/home-routing.module.ts | 13 -------- .../src/app/home/home.component.html | 1 + .../src/app/home/home.component.ts | 16 +++++----- .../src/app/home/home.module.ts | 12 ------- packages/template-blank-ng/src/main.ts | 31 ++++++++++++++++--- packages/template-blank-ng/src/polyfills.ts | 5 +++ packages/template-hello-world-ng/package.json | 28 ++++++++--------- .../src/app/app-routing.module.ts | 18 ----------- .../src/app/app.component.ts | 5 ++- .../src/app/app.module.ts | 16 ---------- .../src/app/app.routes.ts | 9 ++++++ .../src/app/item/item-detail.component.html | 8 ++--- .../src/app/item/item-detail.component.ts | 21 ++++++++----- .../src/app/item/item.service.ts | 18 +++++------ .../src/app/item/items.component.html | 4 +-- .../src/app/item/items.component.ts | 25 +++++++++------ packages/template-hello-world-ng/src/main.ts | 31 ++++++++++++++++--- .../template-hello-world-ng/src/polyfills.ts | 5 +++ 23 files changed, 168 insertions(+), 171 deletions(-) delete mode 100644 packages/template-blank-ng/src/app/app-routing.module.ts delete mode 100644 packages/template-blank-ng/src/app/app.module.ts create mode 100644 packages/template-blank-ng/src/app/app.routes.ts delete mode 100644 packages/template-blank-ng/src/app/home/home-routing.module.ts delete mode 100644 packages/template-blank-ng/src/app/home/home.module.ts delete mode 100644 packages/template-hello-world-ng/src/app/app-routing.module.ts delete mode 100644 packages/template-hello-world-ng/src/app/app.module.ts create mode 100644 packages/template-hello-world-ng/src/app/app.routes.ts diff --git a/packages/template-blank-ng/package.json b/packages/template-blank-ng/package.json index 10e2ddb3..0792690e 100644 --- a/packages/template-blank-ng/package.json +++ b/packages/template-blank-ng/package.json @@ -3,7 +3,7 @@ "main": "src/main.ts", "displayName": "Blank", "templateType": "App template", - "version": "8.8.2", + "version": "8.8.3", "description": "Blank template for NativeScript apps using Angular", "author": "NativeScript Team ", "license": "Apache-2.0", @@ -39,26 +39,26 @@ "url": "https://github.com/NativeScript/NativeScript/issues" }, "dependencies": { - "@angular/animations": "~18.0.0", - "@angular/common": "~18.0.0", - "@angular/compiler": "~18.0.0", - "@angular/core": "~18.0.0", - "@angular/forms": "~18.0.0", - "@angular/platform-browser": "~18.0.0", - "@angular/platform-browser-dynamic": "~18.0.0", - "@angular/router": "~18.0.0", - "@nativescript/angular": "^18.0.0", + "@angular/animations": "~19.0.0", + "@angular/common": "~19.0.0", + "@angular/compiler": "~19.0.0", + "@angular/core": "~19.0.0", + "@angular/forms": "~19.0.0", + "@angular/platform-browser": "~19.0.0", + "@angular/platform-browser-dynamic": "~19.0.0", + "@angular/router": "~19.0.0", + "@nativescript/angular": "^19.0.0", "@nativescript/core": "~8.8.0", "@nativescript/theme": "^3.1.0", "rxjs": "~7.8.0", - "zone.js": "~0.14.0" + "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "~18.0.0", - "@angular/compiler-cli": "~18.0.0", + "@angular-devkit/build-angular": "~19.0.0", + "@angular/compiler-cli": "~19.0.0", "@nativescript/types": "~8.8.0", "@nativescript/webpack": "~5.0.0", - "@ngtools/webpack": "~18.0.0", - "typescript": "~5.4.0" + "@ngtools/webpack": "~19.0.0", + "typescript": "~5.6.0" } } diff --git a/packages/template-blank-ng/src/app/app-routing.module.ts b/packages/template-blank-ng/src/app/app-routing.module.ts deleted file mode 100644 index 6b4d4276..00000000 --- a/packages/template-blank-ng/src/app/app-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core' -import { Routes } from '@angular/router' -import { NativeScriptRouterModule } from '@nativescript/angular' - -const routes: Routes = [ - { path: '', redirectTo: '/home', pathMatch: 'full' }, - { - path: 'home', - loadChildren: () => import('~/app/home/home.module').then((m) => m.HomeModule), - }, -] - -@NgModule({ - imports: [NativeScriptRouterModule.forRoot(routes)], - exports: [NativeScriptRouterModule], -}) -export class AppRoutingModule {} diff --git a/packages/template-blank-ng/src/app/app.component.ts b/packages/template-blank-ng/src/app/app.component.ts index 87f06ae2..b391b909 100644 --- a/packages/template-blank-ng/src/app/app.component.ts +++ b/packages/template-blank-ng/src/app/app.component.ts @@ -1,7 +1,10 @@ -import { Component } from '@angular/core' +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { PageRouterOutlet } from '@nativescript/angular'; @Component({ selector: 'ns-app', - templateUrl: 'app.component.html', + templateUrl: './app.component.html', + imports: [PageRouterOutlet], + schemas: [NO_ERRORS_SCHEMA], }) export class AppComponent {} diff --git a/packages/template-blank-ng/src/app/app.module.ts b/packages/template-blank-ng/src/app/app.module.ts deleted file mode 100644 index c9805d7e..00000000 --- a/packages/template-blank-ng/src/app/app.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core' -import { NativeScriptModule } from '@nativescript/angular' - -import { AppRoutingModule } from './app-routing.module' -import { AppComponent } from './app.component' - -@NgModule({ - bootstrap: [AppComponent], - imports: [NativeScriptModule, AppRoutingModule], - declarations: [AppComponent], - schemas: [NO_ERRORS_SCHEMA], -}) -export class AppModule {} diff --git a/packages/template-blank-ng/src/app/app.routes.ts b/packages/template-blank-ng/src/app/app.routes.ts new file mode 100644 index 00000000..3855eed6 --- /dev/null +++ b/packages/template-blank-ng/src/app/app.routes.ts @@ -0,0 +1,6 @@ +import { Routes } from '@angular/router'; + +export const routes: Routes = [ + { path: '', redirectTo: '/home', pathMatch: 'full' }, + { path: 'home', loadComponent: () => import('./home/home.component').then(m => m.HomeComponent) }, +]; diff --git a/packages/template-blank-ng/src/app/home/home-routing.module.ts b/packages/template-blank-ng/src/app/home/home-routing.module.ts deleted file mode 100644 index 128ef5bf..00000000 --- a/packages/template-blank-ng/src/app/home/home-routing.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core' -import { Routes } from '@angular/router' -import { NativeScriptRouterModule } from '@nativescript/angular' - -import { HomeComponent } from './home.component' - -const routes: Routes = [{ path: '', component: HomeComponent }] - -@NgModule({ - imports: [NativeScriptRouterModule.forChild(routes)], - exports: [NativeScriptRouterModule], -}) -export class HomeRoutingModule {} diff --git a/packages/template-blank-ng/src/app/home/home.component.html b/packages/template-blank-ng/src/app/home/home.component.html index b4d208b7..aede6a94 100644 --- a/packages/template-blank-ng/src/app/home/home.component.html +++ b/packages/template-blank-ng/src/app/home/home.component.html @@ -4,4 +4,5 @@ + diff --git a/packages/template-blank-ng/src/app/home/home.component.ts b/packages/template-blank-ng/src/app/home/home.component.ts index 177cba4f..d1f9e313 100644 --- a/packages/template-blank-ng/src/app/home/home.component.ts +++ b/packages/template-blank-ng/src/app/home/home.component.ts @@ -1,15 +1,15 @@ -import { Component, OnInit } from '@angular/core' +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { + NativeScriptCommonModule, + NativeScriptRouterModule, +} from '@nativescript/angular'; @Component({ selector: 'Home', templateUrl: './home.component.html', + imports: [NativeScriptCommonModule, NativeScriptRouterModule], + schemas: [NO_ERRORS_SCHEMA], }) -export class HomeComponent implements OnInit { - constructor() { - // Use the component constructor to inject providers. - } +export class HomeComponent { - ngOnInit(): void { - // Init your component properties here. - } } diff --git a/packages/template-blank-ng/src/app/home/home.module.ts b/packages/template-blank-ng/src/app/home/home.module.ts deleted file mode 100644 index 5cb1b6c9..00000000 --- a/packages/template-blank-ng/src/app/home/home.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core' -import { NativeScriptCommonModule } from '@nativescript/angular' - -import { HomeRoutingModule } from './home-routing.module' -import { HomeComponent } from './home.component' - -@NgModule({ - imports: [NativeScriptCommonModule, HomeRoutingModule], - declarations: [HomeComponent], - schemas: [NO_ERRORS_SCHEMA], -}) -export class HomeModule {} diff --git a/packages/template-blank-ng/src/main.ts b/packages/template-blank-ng/src/main.ts index 4883e8f9..276c0dfa 100644 --- a/packages/template-blank-ng/src/main.ts +++ b/packages/template-blank-ng/src/main.ts @@ -1,8 +1,31 @@ -import { platformNativeScript, runNativeScriptAngularApp } from '@nativescript/angular'; +import { + bootstrapApplication, + provideNativeScriptHttpClient, + provideNativeScriptNgZone, + provideNativeScriptRouter, + runNativeScriptAngularApp, +} from '@nativescript/angular'; +import { provideExperimentalZonelessChangeDetection } from '@angular/core'; +import { withInterceptorsFromDi } from '@angular/common/http'; +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; +/** + * Disable zone by setting this to true + * Then also adjust polyfills.ts (see note there) + */ +const EXPERIMENTAL_ZONELESS = false; runNativeScriptAngularApp({ - appModuleBootstrap: () => platformNativeScript().bootstrapModule(AppModule), + appModuleBootstrap: () => { + return bootstrapApplication(AppComponent, { + providers: [ + provideNativeScriptHttpClient(withInterceptorsFromDi()), + provideNativeScriptRouter(routes), + EXPERIMENTAL_ZONELESS + ? provideExperimentalZonelessChangeDetection() + : provideNativeScriptNgZone(), + ], + }); + }, }); - diff --git a/packages/template-blank-ng/src/polyfills.ts b/packages/template-blank-ng/src/polyfills.ts index 05df9622..3b995a86 100644 --- a/packages/template-blank-ng/src/polyfills.ts +++ b/packages/template-blank-ng/src/polyfills.ts @@ -7,6 +7,11 @@ import '@nativescript/core/globals'; // Install @nativescript/angular specific polyfills import '@nativescript/angular/polyfills'; +/** + * Disable zone completely by removing the following 3 imports + * alongside also adjusting main.ts to boot zoneless + */ + /** * Zone.js and patches */ diff --git a/packages/template-hello-world-ng/package.json b/packages/template-hello-world-ng/package.json index 33b4590a..fa551540 100644 --- a/packages/template-hello-world-ng/package.json +++ b/packages/template-hello-world-ng/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/template-hello-world-ng", "main": "./src/main.ts", - "version": "8.8.2", + "version": "8.8.3", "author": "NativeScript Team ", "description": "NativeScript Angular Hello World template", "license": "Apache-2.0", @@ -33,26 +33,26 @@ "url": "https://github.com/NativeScript/NativeScript/issues" }, "dependencies": { - "@angular/animations": "~18.0.0", - "@angular/common": "~18.0.0", - "@angular/compiler": "~18.0.0", - "@angular/core": "~18.0.0", - "@angular/forms": "~18.0.0", - "@angular/platform-browser": "~18.0.0", - "@angular/platform-browser-dynamic": "~18.0.0", - "@angular/router": "~18.0.0", - "@nativescript/angular": "^18.0.0", + "@angular/animations": "~19.0.0", + "@angular/common": "~19.0.0", + "@angular/compiler": "~19.0.0", + "@angular/core": "~19.0.0", + "@angular/forms": "~19.0.0", + "@angular/platform-browser": "~19.0.0", + "@angular/platform-browser-dynamic": "~19.0.0", + "@angular/router": "~19.0.0", + "@nativescript/angular": "^19.0.0", "@nativescript/core": "~8.8.0", "@nativescript/theme": "^3.1.0", "rxjs": "~7.8.0", - "zone.js": "~0.14.0" + "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "~18.0.0", - "@angular/compiler-cli": "~18.0.0", + "@angular-devkit/build-angular": "~19.0.0", + "@angular/compiler-cli": "~19.0.0", "@nativescript/types": "~8.8.0", "@nativescript/webpack": "~5.0.0", - "@ngtools/webpack": "~18.0.0", + "@ngtools/webpack": "~19.0.0", "typescript": "~5.4.0" } } diff --git a/packages/template-hello-world-ng/src/app/app-routing.module.ts b/packages/template-hello-world-ng/src/app/app-routing.module.ts deleted file mode 100644 index 248f9dae..00000000 --- a/packages/template-hello-world-ng/src/app/app-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core' -import { Routes } from '@angular/router' -import { NativeScriptRouterModule } from '@nativescript/angular' - -import { ItemsComponent } from './item/items.component' -import { ItemDetailComponent } from './item/item-detail.component' - -const routes: Routes = [ - { path: '', redirectTo: '/items', pathMatch: 'full' }, - { path: 'items', component: ItemsComponent }, - { path: 'item/:id', component: ItemDetailComponent }, -] - -@NgModule({ - imports: [NativeScriptRouterModule.forRoot(routes)], - exports: [NativeScriptRouterModule], -}) -export class AppRoutingModule {} diff --git a/packages/template-hello-world-ng/src/app/app.component.ts b/packages/template-hello-world-ng/src/app/app.component.ts index 5920b7ac..b391b909 100644 --- a/packages/template-hello-world-ng/src/app/app.component.ts +++ b/packages/template-hello-world-ng/src/app/app.component.ts @@ -1,7 +1,10 @@ -import { Component } from '@angular/core' +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { PageRouterOutlet } from '@nativescript/angular'; @Component({ selector: 'ns-app', templateUrl: './app.component.html', + imports: [PageRouterOutlet], + schemas: [NO_ERRORS_SCHEMA], }) export class AppComponent {} diff --git a/packages/template-hello-world-ng/src/app/app.module.ts b/packages/template-hello-world-ng/src/app/app.module.ts deleted file mode 100644 index 2a0ade6a..00000000 --- a/packages/template-hello-world-ng/src/app/app.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core' -import { NativeScriptModule } from '@nativescript/angular' - -import { AppRoutingModule } from './app-routing.module' -import { AppComponent } from './app.component' -import { ItemsComponent } from './item/items.component' -import { ItemDetailComponent } from './item/item-detail.component' - -@NgModule({ - bootstrap: [AppComponent], - imports: [NativeScriptModule, AppRoutingModule], - declarations: [AppComponent, ItemsComponent, ItemDetailComponent], - providers: [], - schemas: [NO_ERRORS_SCHEMA], -}) -export class AppModule {} diff --git a/packages/template-hello-world-ng/src/app/app.routes.ts b/packages/template-hello-world-ng/src/app/app.routes.ts new file mode 100644 index 00000000..c998b860 --- /dev/null +++ b/packages/template-hello-world-ng/src/app/app.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; +import { ItemsComponent } from './item/items.component'; +import { ItemDetailComponent } from './item/item-detail.component'; + +export const routes: Routes = [ + { path: '', redirectTo: '/items', pathMatch: 'full' }, + { path: 'items', component: ItemsComponent }, + { path: 'item/:id', component: ItemDetailComponent }, +]; diff --git a/packages/template-hello-world-ng/src/app/item/item-detail.component.html b/packages/template-hello-world-ng/src/app/item/item-detail.component.html index c572adf7..607827c2 100644 --- a/packages/template-hello-world-ng/src/app/item/item-detail.component.html +++ b/packages/template-hello-world-ng/src/app/item/item-detail.component.html @@ -1,9 +1,9 @@ - - - + + + - + diff --git a/packages/template-hello-world-ng/src/app/item/item-detail.component.ts b/packages/template-hello-world-ng/src/app/item/item-detail.component.ts index 252fa64f..c6b4427b 100644 --- a/packages/template-hello-world-ng/src/app/item/item-detail.component.ts +++ b/packages/template-hello-world-ng/src/app/item/item-detail.component.ts @@ -1,20 +1,25 @@ -import { Component, OnInit } from '@angular/core' +import { Component, NO_ERRORS_SCHEMA, OnInit, inject, signal } from '@angular/core' import { ActivatedRoute } from '@angular/router' - +import { NativeScriptCommonModule } from '@nativescript/angular' import { Item } from './item' import { ItemService } from './item.service' @Component({ - selector: 'ns-details', - templateUrl: './item-detail.component.html', + selector: 'ns-detail', + templateUrl: './detail.component.html', + imports: [NativeScriptCommonModule], + schemas: [NO_ERRORS_SCHEMA], }) export class ItemDetailComponent implements OnInit { - item: Item - - constructor(private itemService: ItemService, private route: ActivatedRoute) {} + itemService = inject(ItemService) + route = inject(ActivatedRoute) + item = signal(null) ngOnInit(): void { const id = +this.route.snapshot.params.id - this.item = this.itemService.getItem(id) + this.item.set(this.itemService.getItem(id)) + + // log the item to the console + console.log(this.item()) } } diff --git a/packages/template-hello-world-ng/src/app/item/item.service.ts b/packages/template-hello-world-ng/src/app/item/item.service.ts index cd15d24e..b8cf2d9a 100644 --- a/packages/template-hello-world-ng/src/app/item/item.service.ts +++ b/packages/template-hello-world-ng/src/app/item/item.service.ts @@ -1,13 +1,13 @@ -import { Injectable } from '@angular/core' - +import { Injectable, signal } from '@angular/core' import { Item } from './item' @Injectable({ providedIn: 'root', }) export class ItemService { - private items = new Array( - { id: 1, name: 'Ter Stegen', role: 'Goalkeeper' }, + items = signal([ + { id: 1, name: 'NativeScript', role: 'Technology' }, + { id: 2, name: 'Ter Stegen', role: 'Goalkeeper' }, { id: 3, name: 'Piqué', role: 'Defender' }, { id: 4, name: 'I. Rakitic', role: 'Midfielder' }, { id: 5, name: 'Sergio', role: 'Midfielder' }, @@ -28,14 +28,10 @@ export class ItemService { { id: 22, name: 'Aleix Vidal', role: 'Midfielder' }, { id: 23, name: 'Umtiti', role: 'Defender' }, { id: 24, name: 'Mathieu', role: 'Defender' }, - { id: 25, name: 'Masip', role: 'Goalkeeper' } - ) - - getItems(): Array { - return this.items - } + { id: 25, name: 'Masip', role: 'Goalkeeper' }, + ]) getItem(id: number): Item { - return this.items.filter((item) => item.id === id)[0] + return this.items().find((item) => item.id === id) } } diff --git a/packages/template-hello-world-ng/src/app/item/items.component.html b/packages/template-hello-world-ng/src/app/item/items.component.html index b23af154..02d3b502 100644 --- a/packages/template-hello-world-ng/src/app/item/items.component.html +++ b/packages/template-hello-world-ng/src/app/item/items.component.html @@ -1,10 +1,10 @@ - + - + diff --git a/packages/template-hello-world-ng/src/app/item/items.component.ts b/packages/template-hello-world-ng/src/app/item/items.component.ts index edd48042..55723bec 100644 --- a/packages/template-hello-world-ng/src/app/item/items.component.ts +++ b/packages/template-hello-world-ng/src/app/item/items.component.ts @@ -1,18 +1,25 @@ -import { Component, OnInit } from '@angular/core' - -import { Item } from './item' +import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core' +import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular' +import { Page } from '@nativescript/core' import { ItemService } from './item.service' @Component({ selector: 'ns-items', templateUrl: './items.component.html', + imports: [NativeScriptCommonModule, NativeScriptRouterModule], + schemas: [NO_ERRORS_SCHEMA], }) -export class ItemsComponent implements OnInit { - items: Array - - constructor(private itemService: ItemService) {} +export class ItemsComponent { + itemService = inject(ItemService) + page = inject(Page) - ngOnInit(): void { - this.items = this.itemService.getItems() + constructor() { + // Setup large titles on iOS + this.page.on('loaded', (args) => { + if (__IOS__) { + const navigationController: UINavigationController = this.page.frame.ios.controller + navigationController.navigationBar.prefersLargeTitles = true + } + }) } } diff --git a/packages/template-hello-world-ng/src/main.ts b/packages/template-hello-world-ng/src/main.ts index 4883e8f9..276c0dfa 100644 --- a/packages/template-hello-world-ng/src/main.ts +++ b/packages/template-hello-world-ng/src/main.ts @@ -1,8 +1,31 @@ -import { platformNativeScript, runNativeScriptAngularApp } from '@nativescript/angular'; +import { + bootstrapApplication, + provideNativeScriptHttpClient, + provideNativeScriptNgZone, + provideNativeScriptRouter, + runNativeScriptAngularApp, +} from '@nativescript/angular'; +import { provideExperimentalZonelessChangeDetection } from '@angular/core'; +import { withInterceptorsFromDi } from '@angular/common/http'; +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; +/** + * Disable zone by setting this to true + * Then also adjust polyfills.ts (see note there) + */ +const EXPERIMENTAL_ZONELESS = false; runNativeScriptAngularApp({ - appModuleBootstrap: () => platformNativeScript().bootstrapModule(AppModule), + appModuleBootstrap: () => { + return bootstrapApplication(AppComponent, { + providers: [ + provideNativeScriptHttpClient(withInterceptorsFromDi()), + provideNativeScriptRouter(routes), + EXPERIMENTAL_ZONELESS + ? provideExperimentalZonelessChangeDetection() + : provideNativeScriptNgZone(), + ], + }); + }, }); - diff --git a/packages/template-hello-world-ng/src/polyfills.ts b/packages/template-hello-world-ng/src/polyfills.ts index 05df9622..3b995a86 100644 --- a/packages/template-hello-world-ng/src/polyfills.ts +++ b/packages/template-hello-world-ng/src/polyfills.ts @@ -7,6 +7,11 @@ import '@nativescript/core/globals'; // Install @nativescript/angular specific polyfills import '@nativescript/angular/polyfills'; +/** + * Disable zone completely by removing the following 3 imports + * alongside also adjusting main.ts to boot zoneless + */ + /** * Zone.js and patches */