The NativeScript team is dedicated to Angular and truly love building apps with it. We are excited to bring Angular 10 support and already looking forward to Angular 11.
In this update we wanted to go the extra mile and also apply some major cleanups to @nativescript/core to bring proper TypeScript 3.9 support to align with Angular 10. In fact, we're introducing some rc versions of the new upcoming NativeScript 7 in some of this support so those looking to upgrade can get ahead with several updates here.
We'll also show a nice new feature that's never been supported with NativeScript Angular previously. Finally true Async APP_INITIALIZER
support! 🎉
If you want to try this quickly, this section is for you. If you want more details, continue further down.
Install the {N} cli (at least 7.0.0 and newer):
npm i -g nativescript
This will install the next upcoming cli version which supports scoped packages (the future of all {N} npm packages). This will still work with older projects so you can just start using this.
It also introduces a new cli alias we call ns
(can be interpreted as NativeScript Compiler
or just simply NativeScript
). tns
still works and will always work. We will use ns
here to introduce it as part of the 2020 roadmap to slowly begin moving away from tns
things.
ns create sampleapp --ng
You now have a NativeScript for Angular 10 app to play with.
Let's breakdown what's needed to try this out right now in your own projects. We plan to keep this in rc for another week to vet any last remaining issues. You can help make a better final release by reporting any issues you encounter here - just prefix the issue with [Angular 10]
so we see it quickly.
npm i -g nativescript
This will install the latest cli version.
"scripts": {
"ngcc": "ngcc --properties es2015 module main --first-only",
"postinstall": "npm run ngcc"
},
"dependencies": {
"@angular/animations": "~10.0.0",
"@angular/common": "~10.0.0",
"@angular/compiler": "~10.0.0",
"@angular/core": "~10.0.0",
"@angular/forms": "~10.0.0",
"@angular/platform-browser": "~10.0.0",
"@angular/platform-browser-dynamic": "~10.0.0",
"@angular/router": "~10.0.0",
"@nativescript/angular": "~10.0.0",
"@nativescript/core": "~7.0.0",
"@nativescript/theme": "~2.3.0",
"reflect-metadata": "~0.1.12",
"rxjs": "^6.6.0",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular/compiler-cli": "~10.0.0",
"@nativescript/types": "~7.0.0",
"@nativescript/webpack": "~3.0.0",
"@ngtools/webpack": "~10.0.0",
"typescript": "~3.9.0"
}
Make sure you completely remove nativescript-angular
and tns-core-modules
from dependencies and/or devDependencies.
The ngcc
and postinstall
is still a good idea to keep and will explain that more in a moment.
If you're used to using tns-platform-declarations
, you can now safely use @nativescript/types
which is the same thing but just named with a bit more clarity. This allows you to update your references.d.ts
as follows:
/// <reference path="./node_modules/@nativescript/types/ios.d.ts" />
/// <reference path="./node_modules/@nativescript/types/android.d.ts" />
If you're used to using nativescript-dev-webpack
, you can now safely use @nativescript/webpack
which is the same thing but now contains all the latest updates from webpack and transient dependencies which also includes up-to-date webpack.config.js files. To replace your own project's webpack.config.js, you can simply delete it, then clean your project using a similar npm script shown above to clean and when you rerun the project the @nativescript/webpack
will simply drop a brand new updated one in your project. If you had custom webpack changes you can use your git changeset to keep your custom bits.
If you have trouble with your webpack config you can copy/paste this one here: https://github.com/NativeScript/NativeScript/blob/204b5a427b11a411ffd70468155e149bda168755/packages/webpack/templates/webpack.angular.js
tsconfig.json
with similar settings (dependending on your project it doesn't have to mirror this exactly but you can use as a good gauge). In general the module
and target
are updated to newer targets.{
"compilerOptions": {
"module": "ESNext",
"target": "es2015",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmitHelpers": true,
"noEmitOnError": true,
"skipLibCheck": true,
"lib": [
"es2018", "es2017", "dom", "es6"
],
"baseUrl": ".",
"paths": {
"~/*": [
"app/*"
]
}
},
"include": [
"references.d.ts",
"src/tests/**/*.ts"
],
"files": [
"./src/main.ts"
],
"exclude": [
"node_modules",
"platforms",
"e2e"
]
}
Update all imports to simply @nativescript/angular
if they were nativescript-angular/{anything}
previously. This includes the Angular 9 import { platformNativeScriptDynamic } from '@nativescript/angular/platform';
in your main.ts
which can be flattened to be 100% consistent across the board. So just import { platformNativeScriptDynamic } from '@nativescript/angular';
.
A note about that ngcc.config.js
and the postinstall, etc.
A lot of plugins out there have not been built with ng-packagr
and/or been built with Angular 9 or 10...yet. This is not a bad thing and is perfectly okay right now. Therefore this file can help bridge the gap to allow those plugins to work right now with your Angular 10 projects. The rule of thumb generally is if you encounter a build complaint about a plugin you may need to add an entry to this file. You can follow a similar pattern with adding entries for different dependencies based on the sample ngcc.config.js
file which is provided as a convenience with nsc create sampleapp --ng
sample app.
ns run ios --emulator
or ns run android --emulator
And report any issues here, thank you! ❤️
file: node_modules/@angular/core/fesm2015/core.js:3380:0: JS ERROR ReferenceError: Can't find variable: setTimeout
(CoreFoundation) *** Terminating app due to uncaught exception 'NativeScript encountered a fatal error: ReferenceError: Can't find variable: setTimeout
Solution:
Make sure import { platformNativeScriptDynamic } from "@nativescript/angular";
is the first import in main.ts
. For example:
import { enableProdMode } from "@angular/core";
import { platformNativeScriptDynamic } from "@nativescript/angular";
import { platformNativeScriptDynamic } from "@nativescript/angular";
import { enableProdMode } from "@angular/core";
CONSOLE ERROR file:///app/bundle.js:3489:19: No value accessor for form control with name: 'someControl',ZoneAwareError(file: node_modules/@nativescript/zone-js/zone-nativescript.js:1298:0)
at _throwError(file: node_modules/@angular/forms/fesm2015/forms.js:2440:0)
Or something similar.
Solution:
This can occur if you have a component that extends an abstract
class which is missing a decoration. To resolve for example:
export abstract class SomeParentClass { ...
@Directive()
export abstract class SomeParentClass { ...
Sometimes you need to fetch data before the app boots up or do async operations before the app is ready for user interaction. Or maybe you just want a neat launch sequence to animate before your app springs to life. With Angular 10 and NativeScript you can now finally use an Async APP_INITIALIZER
just as you can with Angular web apps.
Here's an example:
export function asyncBoot(): Function {
return (): Promise<any> => new Promise(resolve => {
setTimeout(() => {
resolve();
}, 5000);
})
}
@NgModule({
imports: [NativeScriptModule],
declarations: [AppComponent],
bootstrap: [AppComponent],
providers: [
{
provide: APP_INITIALIZER,
useFactory: asyncBoot,
multi: true
},
]
})
export class AppModule {}
You could also inject HttpClient
into that factory function to perform remote requests.
We'll be discussing this in greater detail in a followup blog post to explore a new NativeScript Angular bootstrap option providing the ability to do engaging custom launch animations.