A presentation at JSConf Belgium in May 2018 in Bruges, Belgium by Rowdy Rabouw
Unleash your web skills on native!
Web developer mood coaster
web developer in natural habitat
web developer • HTML • CSS • JavaScript • Sass • Node Package Manager Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 7/124
web developer on native iOS / Android
web developer & native • App stores • Provisioning files • Java or Kotlin for Android • Objective-C or Swift for iOS Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 10/124
web developer with nativescript
web developer & nativescript • App stores • Provisioning files • NativeScript • HTML • CSS • JavaScript • Sass • Node Package Manager Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 13/124
web developer ❤ nativescript
who?
Rowdy Rabouw @rowdyrabouw Gouda, The Netherlands I ❤ superhero movies Freelance web and app developer Lead developer Nationale-Nederlanden Pension App Progress Developer Expert for Nativescript Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 17/124
Mobile App framework decision guide
Mobile App framework decision guide Do you want/need a native User Interface and native performance? No Yes Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 20/124
Mobile App framework decision guide Do you want/need a native User Interface and native performance? No Yes Phonegap / Cordova with Ionic • WebView • DOM to manipulate • HTML styled like native Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 21/124
Mobile App framework decision guide Do you want/need a native User Interface and native performance? No Yes Phonegap / Cordova with Ionic • WebView • DOM to manipulate • HTML styled like native continue Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 22/124
Mobile App framework decision guide Do you have too much money and time? Yes No Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 23/124
Mobile App framework decision guide Do you have too much money and time? Yes No Native iOS and Android • Twice the work Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 24/124
Mobile App framework decision guide Do you have too much money and time? Yes No Native iOS and Android • Twice the work continue Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 25/124
Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 26/124
Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Xamarin • .NET or C# • Cross compiling • Bindings to access native APIs Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 27/124
Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Flutter • Dart • Cross compiling • Beta Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 28/124
Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Flutter • Dart • Cross compiling • Beta continue Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 29/124
Mobile App framework decision guide Do you want to use modern JavaScript? No Yes Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 30/124
Mobile App framework decision guide Do you want to use modern JavaScript? No Yes Titanium • No ES6/ES2015 support • Can't use NPM • Old MVC framework (Alloy) Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 31/124
Mobile App framework decision guide Do you want to use modern JavaScript? No Yes Titanium • No ES6/ES2015 support • Can't use NPM • Old MVC framework (Alloy) continue Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 32/124
Mobile App framework decision guide Do you know and like React? Yes No Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 33/124
Mobile App framework decision guide Do you know and like React? Yes No React Native • React • Native code to access APIs • Version 0.55 Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 34/124
Mobile App framework decision guide Do you know and like React? Yes No React Native • React • Native code to access APIs • Version 0.55 continue Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 35/124
NATIVESCRIPT
NATIVESCRIPT
What is NativeScript? • Open source framework for building truly native mobile apps • JavaScript, markup (XML/HTML) and CSS • Native code inside your JavaScript if you want and dare • Cross Platform: one codebase for iOS and Android • Backed by software company Progress • Android 4.2 or a later stable official release • iOS 7.0 or later stable official release Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 39/124
How to start?
docs.nativescript.org
nativescript.org/get-the-nativescript-book
forum.nativescript.org
nativescriptcommunity.slack.com
nativescript.org/nativescript-sidekick
play.nativescript.org
nativescripting.com
markup like on the web
Markup http://2xr.nl/markup https://docs.nativescript.org/ui/components < ActionBar
title ="Native elements"/> < StackLayout
< Button
text ="Button" tap ="{{ onButtonTap }}"/>
< Switch
checked ="false"/>
< SegmentedBar
items ="{{ segmentedBarItems }}"/>
< Progress
value ="0" maxValue ="100"/>
< Slider
value ="0" minValue ="0" maxValue ="100"/>
< DatePicker
year ="2018" month ="1" day ="1"
minDate ="1970-01-01" maxDate ="2100-12-31"/> </ StackLayout
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 51/124
TextField https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield < TextField /> < TextField
text =""/> < TextField
hint ="Enter your name"/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 53/124
TextField: autocapitalization https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield < TextField
autocapitalizationType ="allCharacters"/> < TextField
autocapitalizationType ="sentences"/> < TextField
autocapitalizationType ="words"/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 54/124
TextField: autocapitalization https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield < TextField
autocapitalizationType ="allCharacters"/> < TextField
autocapitalizationType ="sentences"/> < TextField
autocapitalizationType ="words"/> < TextField
autocapitalizationType ="none"/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 55/124
TextField: autocorrect https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield < TextField
autocorrect ="true"/> < TextField
autocorrect ="false"/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 56/124
TextField: keyboardType http://2xr.nl/keyboardType https://docs.nativescript.org/api-reference/modules/ui_enums.keyboardtype < TextField
keyboardType ="number"/> < TextField
keyboardType ="datetime"/> < TextField
keyboardType ="phone"/> < TextField
keyboardType ="email"/> < TextField
keyboardType ="url"/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 57/124
TextField: more attributes https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield < TextField
textAlignment =""/> < TextField
visibility =""/> < TextField
width =""/> < TextField
maxLength =""/> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 59/124
Layouts https://docs.nativescript.org/ui/layouts Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 60/124
Layouts https://docs.nativescript.org/ui/layouts Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 61/124
DockLayout https://docs.nativescript.org/ui/layouts < DockLayout
height ="100%"
stretchLastChild ="true">
< Label
text ="1" dock ="top"/>
< Label
text ="2" dock ="bottom"/>
< Label
text ="3" dock ="right"/>
< Label
text ="4" dock ="left"/> </ DockLayout
<!-- 1 + 2 have fixed height 3 has fixed width 4 will get all remaining space -->Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 62/124
GridLayout https://docs.nativescript.org/ui/layouts < GridLayout
rows ="100, auto, *"
columns ="100, auto, *">
< Label
text ="1" row ="0" col ="0">
< Label
text ="2" row ="0" col ="1"
colSpan ="2"/>
< Label
text ="3" row ="1" col ="0"
rowSpan ="2"/>
< Label
text ="4" row ="1" col ="1"/>
< Label
text ="5" row ="1" col ="2"/>
< Label
text ="6" row ="2" col ="1"/>
< Label
text ="7" row ="2" col ="2"/> </ GridLayout
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 63/124
Cascading Style Sheets
Cascading Style Sheets https://docs.nativescript.org/ui/styling • a large subset of CSS properties is supported • device-independent pixels • application-wide, page-specific or inline • platform-specific possible • animations • SASS Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 66/124
{N} Core Themes https://docs.nativescript.org/ui/theme • ready to use color schemes • tailored for iOS and Android Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw
NativeScript Theme Builder https://www.nativescriptthemebuilder.com Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 68/124
TabView < TabView
height ="100%">
< StackLayout * tabItem ="{title: 'Rocket Raccoon'}" class ="full rocket"/>
< StackLayout * tabItem ="{title: 'Harley Quinn'}" class ="full harley"/>
< StackLayout * tabItem ="{title: 'Hulk'}" class ="full hulk"/> </ TabView
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 69/124
TabView .full {
background-size : cover;
background-position : center;
background-repeat : no-repeat; } .rocket { background-image : url ( "~/images/rocket-raccoon.jpg" ); } .harley { background-image : url ( "~/images/harley-quinn.jpg" ); } .hulk { background-image : url ( "~/images/hulk.jpg" ); } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 70/124
4 Fantastic Choices
JavaScript
TypeScript
Vue.js
Angular
Native Code
{N} Angular directory structure app/components/slider/ slider.component.html slider.component.ts slider.component.css slider-routing.module.ts slider-module.ts Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 80/124
slider.component.html < ActionBar
title ="Slider"></ ActionBar
< StackLayout
< Slider
value ="70"></ Slider
</ StackLayout
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 81/124
slider.component.ts import { Component } from
"@angular/core" ; @Component({
selector : "app-slider" ,
moduleId : module .id,
templateUrl : "slider.component.html" ,
styleUrls : [ "slider.component.css" ] }) export
class SliderComponent {
constructor () {} } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 82/124
slider.component.css ActionBar {
color : white;
background-color : red; } StackLayout {
padding : 50 ; } Slider {
background-color : red; } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 83/124
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 84/124
slider.component.html < ActionBar
title ="Slider"></ ActionBar
< StackLayout
< Slider
slider-icon
value ="70"></ Slider
</ StackLayout
• attribute directive • changes the appearance or behavior of an element Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 85/124
slider.directive.ts import { Directive, ElementRef } from
"@angular/core" ; import { isIOS } from
"platform" ; @Directive({
selector : "[slider-icon]" }) export
class SliderIconDirective {
constructor (private el: ElementRef) {
if (isIOS) {
let uiSlider = this .el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed( "image.png" ), UIControlState.Normal); } } } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 86/124
slider.directive.ts import { Directive, ElementRef } from
"@angular/core" ; import { isIOS } from
"platform" ; @Directive({
selector : "[slider-icon]" }) export
class SliderIconDirective {
constructor (private el: ElementRef) {
if (isIOS) {
let uiSlider = this .el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed( "image.png" ), UIControlState.Normal); } } } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 87/124
slider.directive.ts import { Directive, ElementRef } from
"@angular/core" ; import { isIOS } from
"platform" ; @Directive({
selector : "[slider-icon]" }) export
class SliderIconDirective {
constructor (private el: ElementRef) {
if (isIOS) {
let uiSlider = this .el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed( "image.png" ), UIControlState.Normal); } } } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 88/124
slider.module.ts import { NgModule, NO_ERRORS_SCHEMA } from
"@angular/core" ; import { NativeScriptModule } from
"nativescript-angular/nativescript.module" ; import { SliderIconDirective } from
"./slider.directive" ; import { SliderRoutingModule } from
"./slider-routing.module" ; import { SliderComponent } from
"./slider.component" ; @NgModule({
imports : [NativeScriptModule, SliderRoutingModule],
declarations : [SliderComponent, SliderIconDirective],
schemas : [NO_ERRORS_SCHEMA] }) export
class SliderModule {} Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 89/124
91/124
Packages & Libraries
Node Package Manager • commonly known as npm • ready to use JavaScript modules • about 650.000 packages of free, reusable code • npm install packagename --save • package.json Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 94/124
Node Package Manager crypto-js Cryptography standards (AES-256) accounting.js Number, money and currency formatting email-validator Email syntax validator Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 95/124
Android Arsenal • libraries for Android (Java / Kotlin) Cocoapods • libraries for iOS (Objective-C / Swift) Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 96/124
Multilingual: ngx-translate
Multilingual: ngx-translate • internationalization library for Angular 2+ • define translations in different languages • switch between them easily • no hardcoded text/labels, all in one place • start directly, even with one language Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 99/124
Multilingual: ngx-translate {
"HOME" : {
"TITLE" : "Hello JSConf Belgium!" ,
"TEXT" : "It's great to introduce NativeScript to you." ,
"SLIDER" : "Slider" ,
"ENGLISH" : "English" ,
"FOREIGN" : "Dutch" ,
"MIP" : "WowWee MiP" ,
"MACHINE_LEARNING" : "Machine Learning" ,
"SPEECH_RECOGNITION" : "Speech Recognition" } } Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 100/124
Multilingual: ngx-translate < ActionBar
[ title ]="'HOME.TITLE' | translate"> </ ActionBar
< Button
[ text ]="'HOME.ENGLISH' | translate" ( tap )="changeLanguage('en')"> </ Button
[] = one way data binding in Angular | = display-value transformations Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 101/124
102/124
NativeScript Plugins
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 105/124
Nativescript cli npm install nativescript -g Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 106/124
Nativescript cli tns create <app-name> tns create <app-name> --tsc tns create <app-name> --ng vue init nativescript-vue/vue-cli-template <app-name> tns create <app-name> --template <template-url> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 107/124
Nativescript cli tns platform add ios tns platform add android tns build ios tns build android tns run ios tns run android Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 108/124
Nativescript cli tns plugin add <plugin-name> Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 109/124
{N} Plugins live demo
Nativescript plugins • nativescript-bluetooth • nativescript-camera • nativescript-social-share • nativescript-speech-recognition • nativescript-texttospeech • nativescript-videoplayer Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 112/124
nativescript-bluetooth import * as bluetooth from
"nativescript-bluetooth" ; bluetooth.isBluetoothEnabled() .then( function ( enabled ) { alert( "Enabled? "
nativescript-bluetooth private uuid = "CA9F644C-1920-4572-8833-1D137A6T2A05" ; bluetooth.startScanning({
seconds : 4 ,
onDiscovered : peripheral => {
if (peripheral.UUID == this .uuid) { bluetooth.connect({
UUID : peripheral.UUID,
onConnected : peripheral => { bluetooth.stopScanning();
// do stuff } }); } } }); Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 114/124
nativescript-camera import * as camera from
"nativescript-camera" ; import { ImageSource } from
"tns-core-modules/image-source" ; camera.requestPermissions(); camera.takePicture({
width : 1000 ,
height : 1000 }) .then( imageAsset => {
new ImageSource().fromAsset(imageAsset).then( imageSource => {
// do something with the image }); }); Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 115/124
nativescript-social-share import * as camera from
"nativescript-camera" ; import { ImageSource } from
"tns-core-modules/image-source" ; import * as SocialShare from
"nativescript-social-share" ; camera.requestPermissions(); camera.takePicture({
width : 1000 ,
height : 1000 }) .then( imageAsset => {
new ImageSource().fromAsset(imageAsset).then( imageSource => { SocialShare.shareImage(imageSource); }); }); Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 116/124
nativescript-speech-recognition import { SpeechRecognition, SpeechRecognitionTranscription }
from
"nativescript-speech-recognition" ; private speechRecognition = new SpeechRecognition(); this .speechRecognition.available().then(
( available: boolean ) =>
console .log(available ? "YES!" : "NO" ), (err: string) => console .log(err) ); this .speechRecognition.requestPermission().then( ( granted: boolean ) => {
console .log( "Granted? "
nativescript-speech-recognition this .speechRecognition.startListening({
locale : "en-US" ,
returnPartialResults : true ,
onResult : ( transcription: SpeechRecognitionTranscription ) => {
console
.log(
User said: ${transcription.text}
);
}
});
this
.speechRecognition.stopListening().then(
()
=>
{
// do something with the recognized text }); Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 118/124
nativescript-texttospeech import { TNSTextToSpeech, SpeakOptions }
from
"nativescript-texttospeech" ; let textToSpeech = new TNSTextToSpeech(); let speakOptions: SpeakOptions = {
text : "Hello world!" ,
locale : "en-GB" ,
speakRate : 0.5 ,
pitch : 0.8 }; textToSpeech.speak(speakOptions); Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 119/124
nativescript-videoplayer < VideoPlayer
src ="video.mp4"
controls ="true"
loop ="true"
autoplay ="false"> </ VideoPlayer
Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 120/124
Win {N} Socks!
Merciekes! 2xr.nl/JSConfBE
Links Native elements playground: http://2xr.nl/markup keyboardType playground: http://2xr.nl/keyboardType TabView playground: http://2xr.nl/TabView Plugin demo app: http://2xr.nl/JSConfBE2018code Unleash your web skills on native! - Rowdy Rabouw - JSConf BE 2018 - @rowdyrabouw 124/124