神刀安全网

Moving from Vanilla JavaScript to Angular 2 in NativeScript

Telerik has recently been emphasizing the support for using Angular 2 to build a NativeScript mobile application. Being able to use a solid JavaScript framework like Angular 2 to build native Android and iOS applications is a huge win for mobile developers. However, what if you’ve been developing NativeScript applications using vanilla JavaScript or TypeScript? What kind of effort is required to transition your application to use Angular 2? In this article, we’ll compare the process of building a NativeScript app using vanilla JavaScript and Angular 2.

I’ve already written an article regarding developing a NativeScript application using Angular 2 , but this time we’re going to take a look at developing a basic NativeScript JavaScript or TypeScript application and then converting it to use the Angular 2 framework instead. The completed apps can be seen in the image below – the simulator on the left is running the vanilla JavaScript version, while the simulator on the right is the Angular 2 version:

Moving from Vanilla JavaScript to Angular 2 in NativeScript

Building a Simple NativeScript JavaScript Project

The project we will create is a simple hashing application. It will have two screens, the first being a list of hash strings based on user input and the second being a crude “about” screen. These screens will be referred to as views or pages. For hashing we’ll be using a third party JavaScript library called jsSHA .

Creating a Fresh Android and iOS JavaScript Project

Let’s start by creating a fresh NativeScript project. Using a Command Prompt (Windows) or Terminal (Mac and Linux), execute the following:

tns create VanillaProject --template tsc cd VanillaProject tns platform add android tns platform add ios

A few things to note above. First you’ll notice we are using the tsc template. This means we are going to be using TypeScript rather than JavaScript. Second, if you’re not using a Mac, you cannot add and build for the iOS platform.

Now we need to create a few directories that will house our two views:

mkdir app/pages mkdir app/pages/list mkdir app/pages/about

Don’t worry about the files that will exist in these directories. We’ll create them when the time comes.

Including the jsSHA JavaScript Library

We can include jsSHA into our project through npm. It can be installed by executing the following from the Terminal or Command Prompt:

npm install jssha --save

This will install only the JavaScript library. Since we are using TypeScript our compiler will throw some errors. I wrote a thorough article regarding the installation of library type definitions , but I’ll summarize it here.

You want to install the Typings package to download library type definitions. With it installed, execute the following:

typings install jssha --save --ambient

This should resolve any compiler errors when using the library in our TypeScript files.

Adding a List Page

We need to build our first application page. It will contain a list of hashed items that are user defined. Let’s start by creating the following files:

touch app/pages/list/list.xml touch app/pages/list/list.ts touch app/pages/list/list-view-model.ts

For OS X and Linux users I’ll be using the `touch` command to make creating files a bit easier. Windows users will need to create the same files manually, or use an equivalent command in their command prompt of choice.

We are following the MVVM rules which is why we have three files. Let’s start with the view model. Open your project’s app/pages/list/list-view-model.ts file and include the following code:

import {Observable} from "data/observable"; import {ObservableArray} from 'data/observable-array'; import * as dialogs from "ui/dialogs"; import * as jsSHA from "jssha";  export class ListModel extends Observable {      items: ObservableArray<Object>;     shaObj: any;      constructor() {         super();         this.items = new ObservableArray("[]");         this.shaObj = new jsSHA("SHA-1", "TEXT");     }      save() {         dialogs.prompt("Text to be hashed...", "").then(result => {             if(result.text != "") {                 this.shaObj.update(result.text);                 this.items.push({text: result.text, hash: this.shaObj.getHash("HEX")});             }         });     } }

Notice how we’re importing the jsSHA library that we installed. We’ll initialize it in the view model constructor function and use it in the save function. When save is called, a prompt dialog will be presented and the result of that prompt will be added to the items array that will be shown on the screen.

Next we need to alter the list model. Open the app/pages/list/list.ts file and include the following code:

import { EventData } from "data/observable"; import { Page } from "ui/page"; import { ListModel } from "./list-view-model"; import * as FrameModule from "ui/frame";  export function navigatingTo(args: EventData) {     var page = <Page>args.object;     page.bindingContext = new ListModel(); }  export function navigateToAbout() {     FrameModule.topmost().navigate({moduleName: "pages/about/about"}); }

Notice how we are including the view model that we previously created. We are also including a function that will navigate to our not yet created “about” page.

Finally we need to create our list view. Open the app/pages/list/list.xml file and include the following markup:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">     <Page.actionBar>         <ActionBar title="Hashes">             <ActionBar.actionItems>                 <ActionItem text="New" tap="{{ save }}" ios.position="right" />             </ActionBar.actionItems>         </ActionBar>     </Page.actionBar>     <ListView items="{{ items }}" itemTap="navigateToAbout">         <ListView.itemTemplate>             <StackLayout>                 <Label text="{{ text }}" />                 <Label text="{{ hash }}" />             </StackLayout>         </ListView.itemTemplate>     </ListView> </Page>

Let’s break down the XML file. We are creating a new page and during the navigation process the navigatingTo function is called which initializes our view model. The page has an action bar with a button that when clicked calls the save method that shows the input prompt. Any data that was added to the items array will be shown in our list view, two properties per line.

Adding an About Page

Although not absolutely necessary, we’re going to create an “about” page. I’m doing this to demonstrate how routing is done using vanilla NativeScript versus Angular 2. The page itself won’t do anything beyond displaying static data.

Create the following files:

touch app/pages/about/about.xml touch app/pages/about/about.ts

Notice we aren’t including a view model for the about page. This is because we don’t have any dynamic data.

We’re going to start with the “about” model. Open the project’s app/pages/about/about.ts file and include the following code:

import { EventData } from "data/observable"; import { Page } from "ui/page";  export function navigatingTo(args: EventData) {     var page = <Page>args.object;     page.bindingContext = {}; }

Not much is happening in the above model. We really only need it so that the page can be navigated to. Let’s crack open the about view. With the app/pages/about/about.xml file open, include the following markup:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">     <Page.actionBar>         <ActionBar title="About">             <NavigationButton text="Back" android.systemIcon="ic_menu_back"></NavigationButton>         </ActionBar>     </Page.actionBar>     <StackLayout>         <Label text="NativeScript Example" />         <Label text="By Nic Raboy" />         <Label text="https://www.thepolyglotdeveloper.com" />     </StackLayout> </Page>

Again, nothing is really happening here. This page only exists for us to see navigation in action. The only navigation logic for the vanilla NativeScript project was the three lines in the list model.

For more information on navigation in a NativeScript application, see a previous post I wrote on the topic.

Changing the Application Bootstrap

We didn’t use all the files that came with our TypeScript template, so let’s change what the default page is. Open the app/app.ts file and include the following code:

import application = require("application"); application.start({ moduleName: "pages/list/list" });

At this point the project should be runnable and ready to go. You can download the finished code here .

Converting the Project to Angular 2

With the vanilla NativeScript project created, we need to convert what we did to the Angular 2 equivalent. Both applications will use TypeScript, but the framework brings many differences.

Creating a Fresh Android and iOS Angular 2 Project

Let’s create a new NativeScript Angular 2 project. From the Command Prompt (Windows) or Terminal (Mac and Linux), execute the following:

tns create AngularProject --ng cd AngularProject tns platform add android tns platform add ios

A few things to note here. Instead of creating a project using the tsc template we are using the --ng tag. This will create an Angular 2 TypeScript project. Also note that just like with the vanilla project, iOS applications can only be built if using a Mac computer.

We’ll also need to create a few directories for our Angular 2 components. Create the following empty directories:

mkdir app/components mkdir app/components/list mkdir app/components/about

We’ll fill these directories as we progress through the tutorial.

Including the jsSHA JavaScript Library

We’re going to follow the same steps when it comes to including jsSHA in our project. From the Command Prompt or Terminal, execute the following:

npm install jssha --save

To include the type definitions for this library in our project we must install them using the Typings package. This can be done like so:

typings install jssha --save --ambient

You need to first install the Typings package to do this. More information on this concept can be seen in a previous article that I wrote.

This should resolve any compiler errors when using the library in our TypeScript files.

Adding a List Component

As we did with the vanilla project, we’re going to start with the list component. Before we can start developing, we need to add the two files we plan to work with. Add the following two files:

touch app/components/list/list.component.ts touch app/components/list/list.xml

Open the project’s app/components/list/list.component.ts file and add the following code:

import {Component} from "@angular/core"; import {Router} from "@angular/router-deprecated"; import * as dialogs from "ui/dialogs"; import * as jsSHA from "jssha";  @Component({     selector: "list",     templateUrl: "./components/list/list.xml", }) export class ListComponent {      router: Router;     items: Array<Object>;     shaObj: any;      constructor(router: Router) {         this.router = router;         this.items = [];         this.shaObj = new jsSHA("SHA-1", "TEXT");     }      save() {         dialogs.prompt("Text to be hashed...", "").then(result => {             if(result.text != "") {                 this.shaObj.update(result.text);                 this.items.push({text: result.text, hash: this.shaObj.getHash("HEX")});             }         });     }      navigateToAbout() {         this.router.navigate(["About"]);     } }

From the TypeScript file we can define the view that is associated to it. Much of this TypeScript file is the same as the vanilla project’s TypeScript file. The core difference is that we’re only using the one and getting rid of the model, view model approach.

With the TypeScript file created we can focus on the UI. Open the project’s app/components/list/list.xml file and include the following markup:

<ActionBar title="Hashes">     <ActionItem text="New" (tap)="save()" ios.position="right"></ActionItem> </ActionBar> <GridLayout>     <ListView [items]="items" (itemTap)="navigateToAbout()">         <template let-item="item">             <StackLayout>                 <Label [text]="item.text"></Label>                 <Label [text]="item.hash"></Label>             </StackLayout>         </template>     </ListView> </GridLayout>

For the most part it is similar to the UI of the vanilla project. The differences here are in the ListView . Variables that are bound to the TypeScript file are made possible by wrapping the square brackets. For example, items is an array of objects, but by using [items] we know that items is not just a static string. This is similar to how we make use of [text] .

Not so bad so far right?

Adding an About Component

Let’s take a look at our simple “about” component. But before we can, we have to create the necessary files. Create the following files in your project:

touch app/components/about/about.component.ts touch app/components/about/about.xml

Like with the vanilla project, the logic is going to be very bare. Open your project’s app/components/about/about.component.ts file and include the following code:

import {Component} from "@angular/core";  @Component({     selector: "about",     templateUrl: "./components/about/about.xml", }) export class AboutComponent {      constructor() {      } }

There are no functions or variables. We just need to map it to a UI so that navigation can happen. Sound familiar?

Let’s take a look at that very basic “about” view. Open the app/components/about/about.xml file and include the following markup:

<ActionBar title="About">     <NavigationButton text="Back" android.systemIcon="ic_menu_back"></NavigationButton> </ActionBar> <StackLayout>     <Label text="NativeScript Angular Example"></Label>     <Label text="Created by Nic Raboy"></Label>     <Label text="https://www.thepolyglotdeveloper.com"></Label> </StackLayout>

The UI is nearly identical to the UI created in the vanilla project.

Navigating with the Angular Router

This is where things can get a little different.

Routing isn’t complicated with Angular 2, but it certainly isn’t three lines of code like we saw in the vanilla project. Open your project’s app/app.component.ts file and include the following code:

import {Component} from "@angular/core"; import {RouteConfig} from "@angular/router-deprecated"; import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "nativescript-angular/router";  import {ListComponent} from "./components/list/list.component"; import {AboutComponent} from "./components/about/about.component";  @Component({     selector: "my-app",     directives: [NS_ROUTER_DIRECTIVES],     providers: [NS_ROUTER_PROVIDERS],     template: "<page-router-outlet></page-router-outlet>" }) @RouteConfig([     { path: "/list", component: ListComponent, name: "List", useAsDefault: true },     { path: "/about", component: AboutComponent, name: "About" }, ]) export class AppComponent {  }

This app/app.component.ts file acts as our main driver, or router, for the entire application. Every component in our application needs to be imported into this file. Inside the @RouteConfig we define how our routing works.

For more information on routing in an Angular 2 application, check out a thorough article I wrote previously on the topic.

Changing the Application Bootstrap

We’re not quite done yet. Just like with the NativeScript JavaScript project we need to alter the bootstrap. Open your project’s app/main.ts file and include the following code:

import {nativeScriptBootstrap} from "nativescript-angular/application"; import {AppComponent} from "./app.component";  nativeScriptBootstrap(AppComponent, null, { startPageActionBarHidden: false });

Essentially we just need to add { startPageActionBarHidden: false } . This is to prevent errors on iOS when the application launches.

At this point the project should be runnable and ready to go. You can download the completed Angular 2 version of the project here .

Conclusion

You just saw how to create a vanilla NativeScript project that uses TypeScript and then how to create that same project using Angular. By creating the same project two times I figured it would be easiest to see the differences.

So why would you want to use Angular 2 rather than just plain JavaScript or TypeScript in a NativeScript application? By using Angular 2 you can recycle most of your TypeScript code into a web application or the other way around. This makes things very convenient. Personally, I also find Angular 2 to be significantly easier to use than NativeScript’s vanilla framework.

There are a few holes in this application. For example, when navigating back from the about page or component, the list view becomes emptied. This is because we don’t persist the data. If you’re interested in persisting this data, check out my application-settings , SQLite , or Couchbase NoSQL tutorials on the subject.

Related resources:

Moving from Vanilla JavaScript to Angular 2 in NativeScript

Moving from Vanilla JavaScript to Angular 2 in NativeScript

Nic Raboy

Nic is a skilled application developer that has released several native and hybrid mobile applications to iTunes and Google Play. He writes about his development experiences related to making web and mobile app development easier to understand and has experience in Android, Node.js, Apache Cordova, Java, NoSQL, SQL, PHP, NativeScript, and Unity3D.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Moving from Vanilla JavaScript to Angular 2 in NativeScript

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址