Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Conquering Mobile with JavaScript: PWAs and NativeScript

Conquering Mobile with JavaScript: PWAs and NativeScript

Are you looking for a comprehensive mobile development strategy that can help you deliver “the right” mobile app for every project? Look no further. This workshop deck explores a complete workflow for building mobile apps with JavaScript (and TypeScript) that can be applied to any mobile project. From achieving maximum reach with Progressive Web Apps, to delivering maximum richness with native apps powered by JavaScript (via NativeScript), the techniques in this workshop give you the tools you need to make sure your mobile app projects don’t fail. Whether you’re looking to get up-to-speed on PWAs or discover how web skills can be used to create native mobile apps, this decks provides insights that can be immediately applied to your next mobile project.

Ee15d938bcfedc4abeb1fbe520a95ab6?s=128

Todd Anglin

March 29, 2018
Tweet

Transcript

  1. Conquering Mobile with JavaScript PWAs and NativeScript @toddanglin

  2. Todd Anglin VP, Product @ @toddanglin anglin@progress.com

  3. None
  4. Agenda PWAs NativeScript Intro Code Sharing AM PM

  5. It's 2018 and we're still talking about how to build

    mobile apps.
  6. What's the problem? Why are you here?

  7. 1. We've built apps, we need a better way 2.

    We're tired of maintaining web AND apps
  8. What we thought. Web Presence Mobile Web Presence iOS app

    Android app Voice skills Chat bots My problem Some else's problem
  9. Reality. Web Presence Mobile Web Presence *Required *Required iOS app

    Android app Preferred for high transaction apps Voice skills Coming soon Chat bots Your problem
  10. Top 3 Problems with "App Strategy v1" 1. Built native

    apps for iOS, Android – too expensive 2. Built hybrid apps – too slow, too janky 3. Built web apps – too limited
  11. None
  12. Reality. Web Presence Mobile Web Presence *Required *Required iOS app

    Android app Preferred for high transaction apps Voice skills Coming soon Chat bots
  13. Okay, okay. But, really. PWA or native app? Which do

    I choose?
  14. None
  15. Common skill set. Shared code. Best of both worlds.

  16. No compromises PWA iOS app Android app Maximum reach, discoverability

    "Light" experience Unlimited power, capability "Premium" experience
  17. Architecture Shared JavaScript/TypeScript Native app stuff Web app stuff Shared

    native UI iOS UI Android UI Web UI
  18. We'll be using JavaScript § It's everywhere § It's the

    web § With TypeScript, it's familiar and easy
  19. Next steps 1. Understand PWAs 2. Understand NativeScript 3. Put

    them together
  20. Progress Web Apps (PWAs) The next evolution of the web

  21. What are PWAs (really)? Why do we need them? And,

    what ever happened to Responsive Web Apps?
  22. Evolution of the web Web 1.0 Responsive Web Design Progressive

    Web Apps Foundation Design for all Screens Design for offline
  23. Pillars of PWA 1. Reliable 2. Fast 3. Engaging 1.

    Progressive 2. Responsive 3. Connectivity independent 4. App-like 5. Safe 6. Discoverable 7. Re-engageable 8. Installable 9. Linkable
  24. "Progressive Web Apps use modern web capabilities to deliver an

    app- like user experience." "Progressive Web Apps work everywhere but are supercharged in modern browsers. ."
  25. Common Myths PWAs are a "Google" thing

  26. Common Myths PWAs only work on Android

  27. Common Myths PWAs only make sense on mobile

  28. Common Myths PWAs will replace mobile apps

  29. DEMO Let's look at some PWAs

  30. Works Offline Loads Fast "App-like"

  31. Service Workers web app manifest "App-like"

  32. Application Shell My App My App Settings Account Something else

    My App 80º Orlando 20º Boston Shell Content Cached on first visit Loaded from network
  33. Approaches to PWA 1. App Shell + SSR for Entry

    Pages 2. App Shell + CSR for Content 3. Full SSR SSR == Server Side Rendering
  34. PWA "minimum requirements" HTTPS Service Worker Web App Manifest

  35. Lighthouse • Check PWA readiness • Detect common problems •

    Audit performance
  36. Demo Lighthouse

  37. Service Worker § It's just a separate JavaScript file §

    Special type of web worker focused on controlling network requests § Runs separate from main thread § Can run in the background (when no tab open) § No direct DOM access § Communicates with main thread via postMessages § One service worker "per scope" § Updated (at least) every 24 hours
  38. Service Worker Server Your page Service Worker GET request HTTPS

    Cache Browser
  39. Service Worker Server Your page GET request HTTPS Older Browser

    if ('serviceworker' in navigator)
  40. None
  41. Service Worker fetch cache API for retrieving content from the

    network API for storing/retrieving cached app content/data
  42. None
  43. Service Worker Lifecycle First Install 1. register 2. install 3.

    activate 4. idle Updates 1. install 2. waiting 3. activate 4. idle navigator.serviceWorker.register('./service-worker.js')
  44. DEMO Starting our PWA with a Service Worker

  45. Caching

  46. Cache strategies § Cache Only § Network Only § Cache

    First, Fallback on Network § Cache First, Then Network § Cache and Network Race § Network First, Fallback on Cache § Generic Fallback
  47. Cache Only For "static" resources that change with "versions" of

    your site Page Cache Service Worker 1 2 3
  48. Network Only For resources that cannot (or should not) be

    cached Page Network Service Worker 1 2 3
  49. Cache First, Fallback on Network Primary offline-first pattern: load from

    cache if available, otherwise fetch Page Cache Service Worker Network x 1 2 3 4
  50. Network First, Fallback on Cache Load new content by default,

    or show cache if offline Page Cache Service Worker Network x 1 2 3 4
  51. Cache First, Then Network Display cached resource immediately, then update

    when network responds Page Cache Service Worker Network 1 1 2 2 3
  52. Cache and Network Race For cases where disk access may

    be slower than network response Page Cache Service Worker Network 1 2 2 3 x 3
  53. Generic Fallback For stuff that's not available in the cache

    OR on the network Page Cache Service Worker Network 1 2 3 x 5 x 4
  54. None
  55. sw-precache § Auto-generates service worker at build time § Can

    handle static and dynamic caching gulp.task('generate-service-worker', function(callback) { var swPrecache = require('sw-precache'); var rootDir = 'app'; swPrecache.write(`${rootDir}/service-worker.js`, { staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff}'], stripPrefix: rootDir }, callback); });
  56. § Evolution of sw-precache & sw-toolbox § JavaScript library to

    handle service worker boilerplate workbox.routing.registerRoute( new RegExp('^https://fonts.(?:googleapis|gstatic).com/(.*)'), workbox.strategies.cacheFirst(), ); workbox.routing.registerRoute( /\.(?:js|css)$/, workbox.strategies.staleWhileRevalidate(), );
  57. DEMO Using sw-precache

  58. Web App Manifest § Evolution of mobile meta tags §

    Control PWA's home screen icon, splash screen, theme colors, start URL § Helps PWA feel more "app like" (on Android) <link rel="manifest" href="/manifest.json">
  59. Image Source: Addy Osmani, https://addyosmani.com/blog/getting-started-with-progressive-web-apps/ Web App Install banner Requires:

    • Web App Manifest • HTTPS • Registered Service Worker • 2 visits, at least 5 min between visits
  60. Image Source: Addy Osmani, https://addyosmani.com/blog/getting-started-with-progressive-web-apps/ Home screen icon & splash

    screen Define: • App icon • App name • App theme color • Splash screen background color • Orientation limits
  61. None
  62. • name • short_name • icons • dir • lang

    Control Home Screen • start_url • display • fullscreen, standalone, minimal-ui, browser • orientation • any, natural, landscape, portrait, landscape-preferred, landscape-secondary, portrait- preferred, portrait-secondary • background_color • theme_color Control App Behavior • description • related_ applications • prefer_ related_ applications • scope Extras
  63. DEMO Adding web app manifest

  64. PWA Frameworks ReactPWA Angular CLI (!) vue-pwa-boilerplate Polymer App Toolbox

    Kendo UI Ionic
  65. Migrating an Existing Site § It's possible! § Best to

    start with a SPA architecture
  66. Additional Web APIs § Background Sync § Payment Request API

    § Web Push Notifications § Web VR
  67. Background Sync // Register your service worker: navigator.serviceWorker.register('/sw.js'); // Then

    later, request a one-off sync: navigator.serviceWorker.ready.then(function(swRegistration) { return swRegistration.sync.register('myFirstSync'); }); self.addEventListener('sync', function(event) { if (event.tag == 'myFirstSync') { event.waitUntil(doSomeStuff()); } }); In app js: In service worker:
  68. None
  69. None
  70. Apple Pay JS Image source: https://developers.bluesnap.com/docs/apple-pay

  71. None
  72. PWA All the things?

  73. PWA Limits Safari Older Browsers Native APIs

  74. iOS & Safari § Some PWA features coming soon §

    BUT some potentially problematic differences
  75. LUNCH Resume @ 1:00 PM

  76. NativeScript Native mobile apps with JavaScript

  77. Hybrid Promise 100% Web 100% Native Hybrid Reach Code/Skill Reuse

    Richness Premium experience Device APIs Best of both?
  78. Binary Choice Native Hybrid Fast to market Best experience

  79. JavaScript- driven native Fast to market Best experience

  80. "Hybrid" Web UI with limited access to native APIs Native

    App Shell WebView Plugins Plugins Entire app lives here
  81. Native App "JavaScript-driven Native" Native UI driven by JavaScript Native

    UI JavaScript-to-Native bridge JavaScript Engine (Your app code runs here) Native APIs
  82. NativeScript (by Telerik) React Native (by Facebook) “JavaScript-drive Native”

  83. “JavaScript-driven Native” • Share code • Reuse existing skills/teams •

    Reuse existing libraries • Native UI (no WebView!) • Full access to device APIs • Immediate access to new OS features Fast to market Best experience
  84. What is NativeScript? • Open source framework (ASLv2) • Create

    native mobile apps for iOS, Android (and eventually Windows 10) • Use JavaScript (“web skills”) • Write once, run everywhere • Share 100% code between iOS/Android • Share 80% code with web • Reuse popular plugins from NodeJS/iOS/Android • Integrates deeply with Angular and TypeScript
  85. 2013 2014 2015 2016 2017 Early prototypes “Core” engineering Public

    launch Adoption ramp-up Mass adoption Project Timeline 30k 170k 1m+
  86. Accelerating adoption NPM Downloads Jan 2016 Mar 2018

  87. None
  88. None
  89. Solid community growth • More than 6000 Slack channel members

    • Expanding community KB (forum.nativescript.org) • 1000+ unique answer providers • Over 800 community created npm plugins for {N} Top Plugins (by downloads): 1. Theme Core 2. Vue 3. Firebase 4. Image Picker 5. Google Maps SDK
  90. Integrations & Ecosystem

  91. Plugin Ecosystem

  92. Plugin Ecosystem Reusable libraries IDEs Verified Plugins

  93. NativeScript Marketplace market.nativescript.org

  94. • Unit tested • Supports iOS & Android VERIFIED •

    Documented • Supports “vanilla” & Angular
  95. Plugins | App Templates | Page Templates | Themes

  96. How does NativeScript work? Under the covers

  97. None
  98. Generated at build time for OS & 3rd party native

    libraries
  99. NativeScript Android example output: JavaScript

  100. NativeScript iOS example JavaScript

  101. None
  102. Runs on V8 JavaScript VM Runs on JavaScriptCore VM

  103. None
  104. NativeScript Module Layer (NML) § Abstractions on native APIs that

    provide unified, cross- platform API § Dozens available out of the box § Easy for developers to add § IMPORTANT: All native APIs still available at JavaScript layer for platform- specific scenarios § NativeScript modules follow Node module’s conventions (CommonJS).
  105. Example: NativeScript file module

  106. None
  107. None
  108. Putting it all together Style with CSS Define UI with

    XML Logic with JavaScript
  109. “Hello World”

  110. Two ways to use NativeScript: NativeScript Sidekick NativeScript CLI

  111. Command Line Interface (CLI) § Use Command Prompt (Win) or

    Terminal (Mac, Linux) § Free, Part of open source project § Requires installation, local environment setup to build for iOS/Android (requires Mac for iOS) § Integrates with Visual Studio Code (via plugin) WHY: More control, Free, Integrate with existing IDEs/code editors WHO: More technical developers used to using CLI, Open source developers
  112. Sidekick § Visual companion to simplify common {N} tasks §

    Build in the cloud (no local install required) § Easiest way to get started WHY: Richer tooling, Easier setup, Platform integrated WHO: Less technical developers, Prefer Platform integrations, Windows developers targeting iOS
  113. Quickly start new apps • Choose from growing list of

    app templates • Pre-integrate with Progress cloud services
  114. Build locally or in the cloud • Build for iOS

    and Android • Use cloud builds to: • Offload local SDK configuration/ maintenance • Build for iOS from Windows • 100 free cloud builds per month • Pay for additional builds • Fast, secure
  115. Plugins for Visual Studio and VSCode • Integrated Sidekick capabilities

    • Deep integration in Visual Studio for native workflow • Build for iOS with cloud builds directly from VS • Plugins for other code editors/IDEs possible in the future • Webstorm • Eclipse
  116. Choice in Architecture JavaScript Write your application using plain JavaScript

    TypeScript Use TypeScript to get Object Oriented features and compile time error checking Angular Use Angular to architect application. Reuse almost all code between web and mobile
  117. None
  118. Starting a new project (CLI) $ npm install –g nativescript

    $ tns create MyFirstProject --ng $ tns run ios
  119. Demo

  120. Basic Styling with CSS

  121. CSS Convention: app.css <-- Global styles [viewName].css <-- View styles

    [viewName].[platform].css @Component({ ... styleUrls: ["./items.component.css"] })
  122. Supported Properties § color § background-color § background-image § background-repeat

    § background-position § background-size § border-color § border-width § border-radius § font § font-family § font-size § font-style § font-weight § text-align § text-decoration § text-transform § vertical-align § horizontal-align § margin § margin-top § margin-right § margin-bottom § margin-left § width § height § min-width § min-height § padding § padding-top § padding-right § padding-bottom § padding-left § visibility § opacity
  123. Supported Selectors § Element § button { color: red; }

    § Class § .mybutton { color: green; } § ID § #myButton { color: #FFF; } § Hierarchical § button .mybutton { … } § button > .mybutton { … } § Attribute § button[attr] { … } § button[attr='val'] { … } § Pseudo § button:highlighted { … }
  124. Sass & LESS § Use Sass or LESS syntax §

    Auto-compiled $ tns install sass OR $tns install less
  125. Theme

  126. Theme Core § Bootstrap for {N} § Pre-defined CSS classes

    to quickly give apps a polished look-and-feel § iOS and Android $ npm install nativescript-theme --save
  127. Theme for text <Label text="Name" class="text- primary text-right"></Label> <Label text="Email"

    class="text- danger"></Label> Change text color: - text-primary, text- muted, text-danger Change text alignment: - text-center, text- left, text-right to Apply text transformation - text-lowercase, text- uppercase, text-capitalize
  128. Theme for buttons General style: - btn, btn-primary, btn-outline, btn-active

    Round buttons: - btn-rounded-sm and btn-rounded-lg Add color (this only work in conjunction with btn-primary): - btn-blue, btn-brown, btn-forest, btn-grey, btn-lemon, btn-lime, btn-ruby and btn-sky
  129. Theme for buttons <Button text="Primary" class="btn btn- primary"></Button> <Button text="Outline"

    class="btn btn- outline"></Button> <Button text="Orange" class="btn btn-primary btn- ornage"></Button> <Button text="Rounded Grey" class="btn btn-primary btn-grey btn-rounded- sm"></Button>
  130. Theme: Other UI components ActionBar styling: <ActionBar title="Title" class="action-bar"></ActionBar> Switch

    styling: <Switch [(ngModel)]="optIn" class="switch"></Switch> Slider styling: <Slider [(ngModel)]="size" class="slider"></Slider>
  131. Theme BEFORE AFTER

  132. Theme margin and padding Use m for Margin and p

    for Padding Add direction: -t: top -b: bottom -l: left -r: right -x: horizontal (left and right) -y: vertical (top and bottom) • 0 • 2 • 4 • 5 • 8 • 10 • 12 • 15 • 16 • 20 • 24 • 25 • 28 • 30 Available size classes:
  133. Theme margin and padding <TextBox class="m-20"... <Label class="m-r-20 p-x-2"... Examples:

    Margin all directions 20: m-20 Margin Right 10: m-r-10 Padding Left and Right 2: p-x-2
  134. Demo Theme and styling

  135. ActionBar Layout + UI

  136. Custom Fonts 1. Use TTF or OTF fonts 2. Put

    fonts in: app > fonts 3. Use in CSS .icon { font-size: 30; font-family: 'FontAwesome'; }
  137. Icon Font Helper § Angular pipe for handling icon fonts

    <Label class="fa" text="\uf293"></Label> <Label class="fa" [text]="'fa-bluetooth' | fonticon"></Label> npm install nativescript-ngx-fonticon --save
  138. Pipes § Transform bound data import { Pipe, PipeTransform }

    from "@angular/core"; @Pipe({ name: "myPipeName" }) export class MyPipe implements PipeTransform { transform(value: number): any { // Do something return newValue; } }
  139. Defining Views

  140. Pages § XML markup structure § Elements (e.g. <Page>, <Label>)

    are NativeScript modules Angular Gotcha Must use closing tags with Angular
  141. Layouts UI Elements

  142. Layouts Absolute Dock Grid Stack Wrap

  143. None
  144. Layouts: FlexBox <div style="display: flex;"> </div> == These are the

    same == <FlexboxLayout> </FlexboxLayout> Supported Flex properties: § Set flex properties via XML, CSS or JS § Uses same syntax as web § Use FlexboxLayout as root element § Same as HTML <div /> with "display: flex;" § Multiple FlexboxLayouts can be nested For containers: • flex-direction • flex-wrap • flex-flow • justify-content • align-items • align-content For children: • order • flex-grow • flex-shrink • flex • align-self • flex-wrap-before
  145. UI Widgets § Button § Label § TextField § TextView

    § SearchBar § Switch § Slider § Progress § ActivityIndicator § Image § ListView § HtmlView § WebView § TabView § SegmentedBar § DatePicker § TimePicker § ListPicker § Dialogs Out-of-the-box Native UI widgets means… • Native behavior • Native perf • Native accessibility • Parity with “native”
  146. Native UI widgets Native API {N} Module button android.widget.Button UIButton

  147. NativeScript Pro UI Powerful collection of native iOS & Android

    UI components for advanced business use cases
  148. NativeScript UI (free) • ListView • SideDrawer • Calendar •

    Chart • DataForm • Gauges • AutoComplete
  149. 3 rows 3 columns

  150. Demo

  151. Targeting Views § Target based on: § screens size §

    minWH<X>, minW<X>, minH<X> § platform § ios, android, windows § Orientation § land, port <file-name>[.<qualifier>]*.<extension> styles.android.css styles.ios.css mypage.minWH600.xml mypage.xml Angular Gotcha Angular projects only support platform targeting
  152. TIP § Platform specific capabilities are always available § JavaScript:

    <view>.android or <view>.ios § Markup: <android></android> or <ios></ios> § Attributes: android:<attribute> or ios:<attribute> § Ex: <label android:class="…" ios:class="…" /> Write once by default. Target specific platform capabilities when needed.
  153. Debugging

  154. “If debugging is the process of removing software bugs, then

    programming must be the process of putting them in.” - Edsger Dijkstra
  155. Debugging Strategies § Debug by alert (no really) § Debug

    by console.log § Debug by Developer Tools § Debug by IDE § Visual Studio § Visual Studio Code
  156. What are your favorite web debugging tools?

  157. Chrome Dev Tools Sources

  158. Chrome Dev Tools Memory

  159. Chrome Dev Tools Network

  160. Chrome Dev Tools Elements

  161. Demo Debugging

  162. Basic Data Binding with Angular

  163. [ value ] or {{ value }} = One way

    binding from class to view
  164. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input value=”{{ message }}”> ` }); export class AppComponent { message: 'Root Component' } app.component.ts
  165. ( event ) = Binds an event to a function

  166. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <label [text]=”message”> <button (tap)=“showMessage($event)”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  167. Events <Label text="Action:" (swipe)="printDirection($event)"> </Label> § If event provides parameters,

    then add $event
  168. Handling Events tap label.on(gestures.GestureTypes.tap, function (args) { console.log("Tap"); }); swipe

    label.on(gestures.GestureTypes.swipe, function (args) { console.log("Swipe Direction: " + args.direction); }); Multiple events label.on("tap, doubleTap, longPress", function (args) { console.log("Event: " + args.eventName); }); § Tap § Double Tap § Long Press § Swipe § Pan § Pinch § Rotation § Touch
  169. [(ngModel)] = Two way binding

  170. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  171. Two-way binding import { NativeScriptFormsModule } from 'natives cript-angular/forms'; …

    imports: [ NativeScriptModule, AppRoutingModule, NativeScriptHttpModule, NativeScriptFormsModule ], § You also need to add NativeScriptForms Module to @NgModule imports
  172. Demo Data binding

  173. Services And Injection

  174. export class MessageService { message: string = ”Service Message” }

    message.service.ts
  175. import { Injectable } from ”@angular/core” export class MessageService {

    message: string = ”Service Message” } message.service.ts
  176. import { Injectable } from ”@angular/core” @Injectable() export class MessageService

    { message: string = ”Service Message” } message.service.ts
  177. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  178. import { Component } from ”@angular/core” import { MessageService }

    from ”./message.service” @Component({ selector: 'app', template: ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  179. @Component({ selector: 'app', providers: [MessageService] template: ` <input [(ngModel)]=”message”> <button

    (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: string; showMessage() { alert(this.message); } constructor(MessageService _messageService) { this.message = _messageService.message; } app.component.ts
  180. Navigation with Angular Routes

  181. Routing configuration const routes: Routes = [ { path: "",

    redirectTo: "/items", pathMatch: "full" }, { path: "items", component: ItemsComponent }, { path: "item/:id", component: ItemDetailComponent }, ]; § Initial routes config in NativeScript with default Angular template
  182. Routing configuration { path: "", redirectTo: "/items", pathMatch: "full" },

    Sets up the default path to redirect to /items path by default When the app starts it will automatically navigate to /items
  183. Routing configuration { path: "items", component: ItemsComponent }, § Sets

    up the items path to navigate to ItemsComponent
  184. Routing configuration { path: "item/:id", component: ItemDetailComponent } Sets up

    the item + id path to navigate to the ItemDetailComponent Additionally it will provide the id as the parameter into the ItemDetailComponent For example: calling navigate to "/item/25" will open the ItemDetailComponent with id = 25
  185. Routing configuration: Parent/Child const routes: Routes = [ { path:

    '', redirectTo: '/articles', pathMatch: 'full' }, { path: 'items', children: [ { path: '', component: ItemsComponent }, { path: ':id', component: ItemDetailComponent }, ]}, { path: 'articles', children: [ { path: '', component: ArticlesComponent }, { path: 'read/:id', component: ArticleComponent }, { path: 'edit/:id', component: EditArticleComponent }, { path: 'search/:tech/:keyword', component: ArticleSearchResultsComponent }, ]}, ];
  186. Routing configuration: Parent/Child const routes: Routes = [ … {

    path: 'articles', children: [ { path: '', component: ArticlesComponent }, { path: "read/:id", component: ArticleComponent }, { path: "edit/:id", component: EditArticleComponent }, { path: "search/:tech/:keyword", component: ArticleSearchResultsComponent } ]} ]; Navigate to "/articles" will trigger this path
  187. Routing configuration: Parent/Child const routes: Routes = [ … {

    path: 'articles', children: [ { path: '', component: ArticlesComponent }, { path: "read/:id", component: ArticleComponent }, { path: "edit/:id", component: EditArticleComponent }, { path: "search/:tech/:keyword", component: ArticleSearchResultsComponent } ]} ]; Navigate to "/articles/read/25" will trigger this path and pass 25 as the id
  188. Routing configuration: Parent/Child const routes: Routes = [ … {

    path: 'articles', children: [ { path: '', component: ArticlesComponent }, { path: "read/:id", component: ArticleComponent }, { path: "edit/:id", component: EditArticleComponent }, { path: "search/:tech/:keyword", component: ArticleSearchResultsComponent } ]} ]; Navigate to "/articles/search/web/angular" will trigger this path and pass web as the tech and angular as the keyword
  189. Navigation from template <Label text="Angular Navigation" [nsRouterLink]="['/articles/read', '5']"> </Label> §

    Add [nsRouterLink] to provide navigation instructions § Will navigate to '/articles/read/5' path
  190. Navigation from template: Relative paths Navigate to parent: [nsRouterLink]="['..']" Navigate

    to sibling: [nsRouterLink]="['../sibling']" Navigate to child: [nsRouterLink]="['./child']" [nsRouterLink]="['child']"
  191. Navigation from template: Clear History <Label text="Back to Articles" [nsRouterLink]="['..']"

    clearHistory="true"> </Label> § Use clearHistory to clear the navigation stack
  192. Navigation with code import { Router } from '@angular/router'; //

    or import { RouterExtensions } from 'nativescript-angular'; Navigation is easy: 1. Import the router you need 2. Inject the router in the constructor 3. Call navigate
  193. Navigation with code constructor(private router: RouterExtensions) { } Navigation is

    easy: 1. Import the router you need 2. Inject the router in the constructor 3. Call navigate
  194. Navigation with code readArticle(id: number) { this.router.navigate(['/articles/read', id]); } Navigation

    is easy: 1. Import the router you need 2. Inject the router in the constructor 3. Call navigate
  195. Router vs RouterExtensions RouterExtensions provides additional options like: - Page

    transition - Navigate back - Clear History - Etc.
  196. Navigation with code: Relative Path import { ActivatedRoute } from

    '@angular/router'; 1. Import ActivatedRoute 2. Inject it in the constructor 3. Provide it as a parameter f or `navigate`, as `relativeTo`
  197. Navigation with code: Relative Path constructor( private router: RouterExtensions, private

    route: ActivatedRoute) { } 1. Import ActivatedRoute 2. Inject it in the constructor 3. Provide it as a parameter f or `navigate`, as `relativeTo`
  198. Navigation with code: Relative Path this.router.navigate(['./read', id], { relativeTo: this.route

    }); 1. Import ActivatedRoute 2. Inject it in the constructor 3. Provide it as a parameter for `navigate`, as `relativeTo`
  199. Navigation with code: Relative path Navigate to parent: this.router.navigate(['..'], {relativeTo:

    this.route}); Navigate to sibling: this.router.navigate(['../sibling'], {relativeTo: this.route}); Navigate to child: this.router.navigate(['./child'], {relativeTo: this.route}); this.router.navigate(['child'], {relativeTo: this.route});
  200. Clear History this.router.navigate(['/articles', { clearHistory: true }]); § To clear

    history just provide clearHistory into navigate, as an optional parameter
  201. Navigating back There are two functions available from RouterExtensions: -

    this.router.back() – goes one step back - this.router.backToPreviousPage() – goes to the previous page
  202. ArticlesComponent back vs backToPreviousPage 1. navigate `/articles` 2. navigate `/articles/read/1`

    3. navigate `/articles/read/4` 4. navigate `/articles/edit/7` ReadComponent EditComponent [1] articles [2] read/1 [3] read/4 [4] edit/6
  203. ArticlesComponent back vs backToPreviousPage this.router.back(); ReadComponent EditComponent [1] articles [2]

    read/1 [3] read/4 [4] edit/6
  204. ArticlesComponent back vs backToPreviousPage this.router.backToPreviousPage(); ReadComponent EditComponent [1] articles [2]

    read/1 [3] read/4 [4] edit/6
  205. Receiving parameters import { ActivatedRoute } from '@angular/router'; 1. Import

    ActivatedRoute 2. Inject it in the constructor 3. Extract the params from route.snapshot. params
  206. Receiving parameters constructor( private router: RouterExtensions, private route: ActivatedRoute) {

    } 1. Import ActivatedRoute 2. Inject it in the constructor 3. Extract the params from route.snapshot. params
  207. Receiving parameters ngOnInit() { this.tech = this.route.snapshot.params['tech']; this.keyword = this.route.snapshot.params['keyword'];

    this.searchArticles(this.tech, this.keyword); } 1. Import ActivatedRoute 2. Inject it in the constructor 3. Extract the params from route.snapshot. params
  208. Receiving parameters: Navigating to self ngOnInit() { this.route.params.forEach(params => {

    this.tech = params['tech']; this.keyword = params['keyword']; this.searchArticles(this.tech, this.keyword); }); } § Use route.params Observable and then the snapshot
  209. Page Transitions § curl (same as curlUp) (iOS only) §

    curlUp (iOS only) § curlDown (iOS only) § explode (Android only) § fade § flip (same as flipRight) § flipRight § flipLeft § slide (same as slideLeft) § slideLeft § slideRight § slideTop § slideBottom
  210. Using Transition from Template <Button text="Open Path" [nsRouterLink]="['/path']" pageTransition="slideBottom"> </Button>

    § Add pageTransition and the name of the required transition
  211. Use Transition from Code this.router.navigate(['/relative/path'], { transition: { name: 'slideBottom',

    duration: 500, curve: 'linear' } }); § Provide transition attribute into the optional parameters
  212. Animations

  213. Animations 1. Leveraging Angular-style animation 2. Use NativeScript's built-in animation

    library 3. Use Animate.css 4. Use CSS keyframe animation techniques 5. Use Lottie (AirBnB's library) or Keyframes (by Facebook) animations 6. Use a community-generated animation plugin
  214. Animations @keyframes zoom { from { transform: scale(0.5, 0.5) }

    40% { transform: scale(1.6, 1.6) } to { transform: scale(1.0,1.0) } } .zoom { animation-name: zoom; animation-duration: 2s; } § CSS keyframe animation example
  215. Animations <Label [text]="'Coding power:' + profile.codingPower" class="text-primary” [class.zoom]="profile.codingPower > 7">

    </Label> § Apply animations to a UI component using markup or JavaScript
  216. Animation basics Animate: § opacity § backgroundColor § translateX and

    translateY § scaleX and scaleY § rotate Configure: § target (UI element) § duration (in ms) § delay § iterations § curve
  217. Simple animation var view = page.getViewById("myLabel"); view.animate({ translate: { x:

    0, y: 100}, duration: 1000, curve: enums.AnimationCurve.easeIn }); § Animations can be chained together § Multiple properties and elements can be animated § Return a promise that can be canceled
  218. Demo Animations

  219. Code Sharing § One code base, web and mobile §

    Share logic, routes, etc § Build views optimized for each platform
  220. Options § Start with a "seed" project § Convert an

    existing {N} project § Convert an existing Angular web project (coming soon)
  221. Why do this? § Improve developer workflow across web, mobile

    § Share more code/assets between web, mobile § Deliver web, mobile updates simultaneusly
  222. http://bit.ly/code-sharing Web and Mobile Code Sharing with Angular and NativeScript

  223. Wrap-up

  224. NativeScript for Angular Mobile Development Available on Packt by Nathan

    Walker & Nathanael Anderson
  225. The NativeScript Book Available. for FREE. by The Brosteins nativescript.org/book

  226. nativescripting.com

  227. Building Progressive Web Apps Tal Ater

  228. No compromises PWA iOS app Android app Maximum reach, discoverability

    "Light" experience Unlimited power, capability "Premium" experience +
  229. Architecture Shared JavaScript/TypeScript Native app stuff Web app stuff Shared

    native UI iOS UI Android UI Web UI
  230. When should you add PWA? When should add {N}?

  231. • Largely read-only • Simple user interactions • Mostly dynamic

    content • No need to access device APIs • No need for encrypted device storage • Web distribution • Frequently used • More complex user interactions • Need for access to device APIs • Need for encrypted storage • App store distribution PWA
  232. Thanks! @toddanglin anglin@progress.com