KEMBAR78
Nativescript angular | PDF
<3
NATIVESCRIPT DEVELOPER DAY EUROPE
CHRIS NORING
GOOGLE DEVELOPER EXPERT
NATIVESCRIPT DEVELOPER EXPERT
@CHRIS_NORING
STRUCTURE
STRUCTURE
▸ Set up
▸ Commands & Productivity Tools
▸ Project anatomy
▸ Components & Bindings
▸ Routing
▸ Forms
▸ Http
▸ Testing
SET UP
SET UP
SET UP YOUR ANGULAR APPLICATION
▸ introducing nativescript-cli
▸ Scaffold
▸ an application tns create <App name>
▸ an Angular application
▸ tns create <App name> —ng
▸ tns create <App name> --template angular
COMMANDS & PRODUCTIVITY TOOLS
COMMANDS & PRODUCTIVITY TOOLS
USEFUL COMMANDS
▸ Runs your project, tns run <android/ios>
▸ View available commands, tns help
▸ Adds target platforms, tns platform add <android/ios>
▸ Verify connected device is recognized, tns device
▸ Downloads and installs app package on device, tns deploy
<android/ios>
VS CODE PLUGINS
COMMANDS & PRODUCTIVITY TOOLS
Scaffolds Nativescript
component ,template
Test, CSS
Code completion
Helps with imports
Snippets
Support for inline
Templates
PROJECT ANATOMY
PROJECT ANATOMY
BOOTSTRAPPING
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
Nativescript
Angular
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
PROJECT ANATOMY
ROOT MODULE - NATIVESCRIPT MODULE
@NgModule({
imports: [
NativeScriptModule,
AppRoutingModule
]
})
export class ApplicationModule {}
This one is needed
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
PROJECT ANATOMY
ROOT MODULE - ROUTING SET UP
const routes: Routes = [
{ path: "", redirectTo: "/items", pathMatch: "full" },
{ path: "items", component: ItemsComponent },
{ path: "item/:id", component: ItemDetailComponent },
];
Defining routes
@NgModule({
imports: [NativeScriptRouterModule.forRoot(Routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule {}
Setting up separate routing module
@NgModule({
imports: [
NativeScriptModule,
AppRoutingModule
]
})
Importing our route module
Nativescripts version of the router
forRoot() as with Angular
COMPONENTS & BINDINGS
COMPONENTS & BINDINGS
BINDINGS
▸ string interpolation {{}}
▸ attribute binding
▸ banana in a box
▸ event binding
INTERPOLATION
COMPONENTS & BINDINGS
<Label [text]=“{{test | pipe }}”></Label>
ATTRIBUTE BINDING
<Label [text]=“test”></Label>
@Component({
template : `
<StackLayout class="page">
<Label [text]="test"></Label>
</StackLayout>
`
})
export class TestComponent {
test ="test me"
}
EVENT BINDING
@Component({
template : `
<StackLayout class="page">
<Label (tap)=“tapMe()” [text]="test"></Label>
</StackLayout>
`
})
export class TestComponent {
test ="test me"
tapMe() { }
}
COMPONENTS & BINDINGS
BANANA IN A BOX
<StackLayout class=“page">
<TextField [(ngModel)]=“product”></TextField>
</StackLayout>
@Component({})
export class ProductComponent {
product =“”
}
@NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptFormsModule,
})
COMPONENTS & BINDINGS
BASIC COMPONENTS
COMPONENTS & BINDINGS
<Switch></Switch> Radio button
<Label></Label> Span, free text
<ListView></ListView> UL and LI
<TextField></TextField> <input type=“text”>
<Button></Button> <button></button>
<Image></Image> <img>
Check box
Missing
ROUTING
ROUTING
ROUTING - COMPONENT BASED
<Label pageTransition="flip" [nsRouterLink]="['/item', item.id]" [text]="item.name"
class="list-group-item"></Label>
same ol router link prefixed with ns
<router-outlet></router-outlet> where to render the content
ROUTING
ROUTING - PAGE BASED
<page-router-outlet></page-router-outlet> One per app
<ActionBar title="My App" class="action-bar">
</ActionBar>
Native navigation, back
Programmatic navigationflipToNextPage() {
this.routerExtensions.navigate(["/main"], {
transition: { name: “flip", duration: 2000, curve: “linear" }
});
} You change the entire page content
FORMS
FORMS
TEMPLATE FORMS
<Button *ngIf="usernameModel.valid && passwordModel.valid"
(tap)="Save()"
text=“Save">
</Button>
Show ‘save’ button if both
fields are valid
ngForm is missing, which is
why we do this instead, per field
@NgModule({
imports: [
NativeScriptFormsModule,
]
})
<TextField required
#usernameModel="ngModel"
[(ngModel)]="username" >
</TextField>
<TextField required
#passwordModel="ngModel"
[(ngModel)]="password" >
</TextField>
Define the fields
FORMS
REACTIVE FORMS
constructor(
private formBuilder: FormBuilder) {
this.form = this.fb.group({
"name": ["", [Validators.required]]
});
}
Creating our form and fields
@NgModule({
imports: [
ReactiveFormsModule,
]
})
<StackLayout [formGroup]="form">
<TextField formControlName="name"></TextField>
<Label text="{{ form.get('name').value }}"></Label>
<Label text="Name value {{ form.get('name').status | json }}"></Label>
<Label text="Name status {{ form.value | json }}"></Label>
<Label text="Form status {{ form.status | json }}"></Label>
</StackLayout>
HTTP
HTTP
PROMISE BASED HTTP
var http = require('http');
http.getString(“url”)
.then(
(str) => console.log(str),
(err) => console.error(err)
);
http.getJSON(“url")
.then(
(json) => console.log(json),
(err) => console.error(err)
)
http.getImage(“path-to-file.png“)
.then(
(image) => console.log(image),
(err) => console.error(err)
)
http.getFile(“path-to-file.txt“)
.then(
(file) => console.log(file),
(err) => console.error(err)
)
HTTP
ANGULAR HTTP import { NativeScriptHttpModule }
from ‘nativescript-angular';
@NgModule({
imports : [.NativeScriptHttpModule ]
})
export class AppModule {}
import { Http } from '@angular/http';
class ProductService {
constructor(private http: Http) { }
getProducts() {
return this.http.get("url")
.map(result => JSON.parse(result.json()))
}
}
import 'rxjs/add/operator/map';
Inject Http service
Apply operators
TESTING
TEST
SET UP & RUN TESTING
tns test init Creates app/tests, not in release builds
Creates a sample test
Installs the nativescript-unit-test-runner
npm i @types/jasmine --save-dev Install TypeScript typings
tns test <ios/android>
Run the tests
tns test <ios/android> --watch Run tests on code change
Generates component + test
TEST
TEST THE COMPONENTimport { TestBed, inject } from '@angular/core/testing';
import { ProductDetailComponent } from './product-detail.component';
describe('a product-detail component', () => {
let component: ProductDetailComponent;
});
Suite
Set upbeforeEach(() => {
TestBed.configureTestingModule({
providers: [
ProductDetailComponent
]
});
});
Set upbeforeEach(inject([ProductDetailComponent], (ProductDetailComponent) => {
component = ProductDetailComponent;
}));
Testit('should have an instance', () => {
expect(component).toBeDefined();
});
NGZONE
NGZONE
CHANGE DETECTION NOT PICKED UP
Programmatically add view children
Using the FPS component
Changes are not picked up
Use NgZone
import {NgZone} from ‘@angular/core’;
@Component({})
export class SomeComponent {
constructor( private zone: NgZone ) {
}
doChange() {
this.zone.run(() => { this.prop = “new value”; })
}
}
SUMMARY
SUMMARY
WE HAVE COVERED
▸ Set Up
▸ Components & Bindings
▸ Forms
▸ Routing
▸ Testing
▸ Http
▸ There are minor differences
▸ Nativescript truly embraces Angular
@chris_noring
THANK YOU

Nativescript angular

  • 1.
    <3 NATIVESCRIPT DEVELOPER DAYEUROPE CHRIS NORING GOOGLE DEVELOPER EXPERT NATIVESCRIPT DEVELOPER EXPERT @CHRIS_NORING
  • 2.
    STRUCTURE STRUCTURE ▸ Set up ▸Commands & Productivity Tools ▸ Project anatomy ▸ Components & Bindings ▸ Routing ▸ Forms ▸ Http ▸ Testing
  • 3.
  • 4.
    SET UP SET UPYOUR ANGULAR APPLICATION ▸ introducing nativescript-cli ▸ Scaffold ▸ an application tns create <App name> ▸ an Angular application ▸ tns create <App name> —ng ▸ tns create <App name> --template angular
  • 5.
  • 6.
    COMMANDS & PRODUCTIVITYTOOLS USEFUL COMMANDS ▸ Runs your project, tns run <android/ios> ▸ View available commands, tns help ▸ Adds target platforms, tns platform add <android/ios> ▸ Verify connected device is recognized, tns device ▸ Downloads and installs app package on device, tns deploy <android/ios>
  • 7.
    VS CODE PLUGINS COMMANDS& PRODUCTIVITY TOOLS Scaffolds Nativescript component ,template Test, CSS Code completion Helps with imports Snippets Support for inline Templates
  • 8.
  • 9.
    PROJECT ANATOMY BOOTSTRAPPING import {platformNativeScriptDynamic } from "nativescript-angular/platform"; Nativescript Angular import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
  • 10.
    PROJECT ANATOMY ROOT MODULE- NATIVESCRIPT MODULE @NgModule({ imports: [ NativeScriptModule, AppRoutingModule ] }) export class ApplicationModule {} This one is needed import { NativeScriptModule } from "nativescript-angular/nativescript.module";
  • 11.
    PROJECT ANATOMY ROOT MODULE- ROUTING SET UP const routes: Routes = [ { path: "", redirectTo: "/items", pathMatch: "full" }, { path: "items", component: ItemsComponent }, { path: "item/:id", component: ItemDetailComponent }, ]; Defining routes @NgModule({ imports: [NativeScriptRouterModule.forRoot(Routes)], exports: [NativeScriptRouterModule] }) export class AppRoutingModule {} Setting up separate routing module @NgModule({ imports: [ NativeScriptModule, AppRoutingModule ] }) Importing our route module Nativescripts version of the router forRoot() as with Angular
  • 12.
  • 13.
    COMPONENTS & BINDINGS BINDINGS ▸string interpolation {{}} ▸ attribute binding ▸ banana in a box ▸ event binding
  • 14.
    INTERPOLATION COMPONENTS & BINDINGS <Label[text]=“{{test | pipe }}”></Label> ATTRIBUTE BINDING <Label [text]=“test”></Label> @Component({ template : ` <StackLayout class="page"> <Label [text]="test"></Label> </StackLayout> ` }) export class TestComponent { test ="test me" }
  • 15.
    EVENT BINDING @Component({ template :` <StackLayout class="page"> <Label (tap)=“tapMe()” [text]="test"></Label> </StackLayout> ` }) export class TestComponent { test ="test me" tapMe() { } } COMPONENTS & BINDINGS
  • 16.
    BANANA IN ABOX <StackLayout class=“page"> <TextField [(ngModel)]=“product”></TextField> </StackLayout> @Component({}) export class ProductComponent { product =“” } @NgModule({ bootstrap: [ AppComponent ], imports: [ NativeScriptFormsModule, }) COMPONENTS & BINDINGS
  • 17.
    BASIC COMPONENTS COMPONENTS &BINDINGS <Switch></Switch> Radio button <Label></Label> Span, free text <ListView></ListView> UL and LI <TextField></TextField> <input type=“text”> <Button></Button> <button></button> <Image></Image> <img> Check box Missing
  • 18.
  • 19.
    ROUTING ROUTING - COMPONENTBASED <Label pageTransition="flip" [nsRouterLink]="['/item', item.id]" [text]="item.name" class="list-group-item"></Label> same ol router link prefixed with ns <router-outlet></router-outlet> where to render the content
  • 20.
    ROUTING ROUTING - PAGEBASED <page-router-outlet></page-router-outlet> One per app <ActionBar title="My App" class="action-bar"> </ActionBar> Native navigation, back Programmatic navigationflipToNextPage() { this.routerExtensions.navigate(["/main"], { transition: { name: “flip", duration: 2000, curve: “linear" } }); } You change the entire page content
  • 21.
  • 22.
    FORMS TEMPLATE FORMS <Button *ngIf="usernameModel.valid&& passwordModel.valid" (tap)="Save()" text=“Save"> </Button> Show ‘save’ button if both fields are valid ngForm is missing, which is why we do this instead, per field @NgModule({ imports: [ NativeScriptFormsModule, ] }) <TextField required #usernameModel="ngModel" [(ngModel)]="username" > </TextField> <TextField required #passwordModel="ngModel" [(ngModel)]="password" > </TextField> Define the fields
  • 23.
    FORMS REACTIVE FORMS constructor( private formBuilder:FormBuilder) { this.form = this.fb.group({ "name": ["", [Validators.required]] }); } Creating our form and fields @NgModule({ imports: [ ReactiveFormsModule, ] }) <StackLayout [formGroup]="form"> <TextField formControlName="name"></TextField> <Label text="{{ form.get('name').value }}"></Label> <Label text="Name value {{ form.get('name').status | json }}"></Label> <Label text="Name status {{ form.value | json }}"></Label> <Label text="Form status {{ form.status | json }}"></Label> </StackLayout>
  • 24.
  • 25.
    HTTP PROMISE BASED HTTP varhttp = require('http'); http.getString(“url”) .then( (str) => console.log(str), (err) => console.error(err) ); http.getJSON(“url") .then( (json) => console.log(json), (err) => console.error(err) ) http.getImage(“path-to-file.png“) .then( (image) => console.log(image), (err) => console.error(err) ) http.getFile(“path-to-file.txt“) .then( (file) => console.log(file), (err) => console.error(err) )
  • 26.
    HTTP ANGULAR HTTP import{ NativeScriptHttpModule } from ‘nativescript-angular'; @NgModule({ imports : [.NativeScriptHttpModule ] }) export class AppModule {} import { Http } from '@angular/http'; class ProductService { constructor(private http: Http) { } getProducts() { return this.http.get("url") .map(result => JSON.parse(result.json())) } } import 'rxjs/add/operator/map'; Inject Http service Apply operators
  • 27.
  • 28.
    TEST SET UP &RUN TESTING tns test init Creates app/tests, not in release builds Creates a sample test Installs the nativescript-unit-test-runner npm i @types/jasmine --save-dev Install TypeScript typings tns test <ios/android> Run the tests tns test <ios/android> --watch Run tests on code change Generates component + test
  • 29.
    TEST TEST THE COMPONENTimport{ TestBed, inject } from '@angular/core/testing'; import { ProductDetailComponent } from './product-detail.component'; describe('a product-detail component', () => { let component: ProductDetailComponent; }); Suite Set upbeforeEach(() => { TestBed.configureTestingModule({ providers: [ ProductDetailComponent ] }); }); Set upbeforeEach(inject([ProductDetailComponent], (ProductDetailComponent) => { component = ProductDetailComponent; })); Testit('should have an instance', () => { expect(component).toBeDefined(); });
  • 30.
  • 31.
    NGZONE CHANGE DETECTION NOTPICKED UP Programmatically add view children Using the FPS component Changes are not picked up Use NgZone import {NgZone} from ‘@angular/core’; @Component({}) export class SomeComponent { constructor( private zone: NgZone ) { } doChange() { this.zone.run(() => { this.prop = “new value”; }) } }
  • 32.
  • 33.
    SUMMARY WE HAVE COVERED ▸Set Up ▸ Components & Bindings ▸ Forms ▸ Routing ▸ Testing ▸ Http ▸ There are minor differences ▸ Nativescript truly embraces Angular
  • 34.