Javascript required
Skip to content Skip to sidebar Skip to footer

How to Build Android App With Angular

How to Build Android App With Angular

Create A Mobile App From Your Athwart Web App With NativeScript

Angular is all the rage right at present. It is a significant step in the right direction from its predecessor AngularJS 1 for numerous reasons, one being its decoupling from the certificate object model (DOM). This separation allows for applications to exist built beyond the spider web browser. Have for case, the mobile development framework NativeScript, which allows you to develop native Android and iOS applications. In that location is no DOM in this framework, but still we tin can nevertheless utilise Angular to develop our applications.

Nosotros're going to take a wait at how to take an Angular web application and bring it to mobile using NativeScript.

Angular Web Application to NativeScript

The Requirements

In that location are only a few requirements to brand this project successful.

Node.js ships with a very important tool called the Node Bundle Manager (NPM). With it we can get all dependencies for both the Angular web awarding and NativeScript mobile application. Angular support didn't get available in NativeScript until version two.0. Finally, to build for Android or iOS you demand the various platform SDKs.

Building the Athwart Spider web Application

To keep things simple we're going to build an Angular web application from the footing upwards. This way we can understand each component of the application making it easier to convert. The awarding will be a simple listing based application, something y'all've probably seen many times, simply it is all the same a great learning case.

To create the web application we're going to brand use of the Angular CLI. Assuming it has already been installed, execute the following from a Command Prompt (Windows) or Terminal (Mac and Linux):

All the command line work that comes side by side volition be done from within the project directory that was just created. Everything has already been bootstrapped for us in that directory, we just demand to add together the various components and awarding logic.

Let'southward create ii routes which volition represent the pages of our application. Since the Angular CLI is still in beta, information technology cannot withal generate routes then nosotros must do it manually. Using the Terminal or Command Prompt, execute the following:

                                          mkdir -p src/app/list                                                            mkdir -p src/app/create                                                            touch on src/app/list/list.component.ts                                                            touch src/app/list/list.component.html                                                            touch src/app/list/list.component.css                                                            touch src/app/create/create.component.ts                                                            bear on src/app/create/create.component.html                                                            touch src/app/create/create.component.css                                                    

The above commands will generate two unlike pages. If your operating system does not support the above mkdir and touch commands, go ahead and create the files and directories manually.

Since I'm not a design magician, I'm going to lean on Bootstrap for all stylings in this particular web application. To include Bootstrap, execute the following:

                                          npm install bootstrap --save                                                    

Although downloaded, information technology all the same needs to be included in the project. Open up the project's angular-cli-build.js file and add together the post-obit line to the list of vendorNpmFiles:

Finally, the Bootstrap files can be referenced in the projection's src/alphabetize.html file. Open it and include the following at the bottom of the <head> tag:

                                          <link rel="stylesheet" href="vendor/bootstrap/dist/css/bootstrap.min.css" />                                                    

Now that the nuts are set up we can begin coding the application.

Creating a Page for Showing a Listing of Data

We're going to focus on edifice up our page that volition bear witness a list of user entered information. We're going to spend our time in two detail files, one existence a UI file and one beingness a logic file.

Starting with the logic file, open up the projection'due south src/app/list/list.component.ts file and include the following code:

                                          import { Component, OnInit } from '@athwart/cadre';                                                            import { Router } from '@angular/router';                                                            import { Location } from '@athwart/mutual';                                                                                                                        @Component({                                                                              moduleId: module.id,                                                                              selector: 'app-list',                                                                              templateUrl: 'list.component.html',                                                                              styleUrls: ['list.component.css']                                                            })                                                            consign grade ListComponent implements OnInit {                                                                                                                                          public personList: Array<Object>;                                                                                                                                          constructor(individual router: Router, individual location: Location) {                                                                              this.personList = localStorage.getItem("people") != null ? JSON.parse(localStorage.getItem("people")) : [];                                                                              this.location.subscribe((path) => {                                                                              this.personList = localStorage.getItem("people") != goose egg ? JSON.parse(localStorage.getItem("people")) : [];                                                                              });                                                                              }                                                                                                                                          ngOnInit() {}                                                                                                                                          create() {                                                                              this.router.navigate(["/create"]);                                                                              }                                                                                                                        }                                                    

We should probably break down the above code to see what is happening.

The starting time affair that we're doing is we're importing the various dependency components for use. For example, we include the Router so that we tin somewhen navigate to the next page. Nosotros include Location so that we can mind for popular events in the navigation stack, likewise known equally going backwards.

The Angular CLI took care of bootstrapping the @Component for us which essentially tells united states which HTML file to pair with this logic file. We'll design the HTML file in a scrap.

By making the personList public we are assuasive the list to be bound to our HTML UI. This means it will be able to be rendered in the front-terminate.

                                          constructor(individual router: Router, individual location: Location) {                                                                              this.personList = localStorage.getItem("people") != zero ? JSON.parse(localStorage.getItem("people")) : [];                                                                              this.location.subscribe((path) => {                                                                              this.personList = localStorage.getItem("people") != nothing ? JSON.parse(localStorage.getItem("people")) : [];                                                                              });                                                            }                                                    

The above constructor will initialize our list. For the web application we will brand apply of HTML5 local storage for storing our data. Things volition be slightly different for NativeScript, merely not past much. Essentially we're proverb, parse the serialized local storage information if it exists or use an empty array if it does not exist. Past using the subscribe method on the location object we are listening for the pop event in the navigation stack. When this event happens nosotros tin reload from local storage.

                                          create() {                                                                              this.router.navigate(["/create"]);                                                            }                                                    

Finally we accept our create method that volition navigate to the other page or route.

Earlier we go into coding the next folio, let's look at the HTML file that is paired with the TypeScript code that we simply wrote. Open the project'south src/app/list/list.component.html file and include the following markup:

                                          <div grade="container">                                                                              <div class="console console-default">                                                                              <div class="panel-heading">                                                                              <strong>Spider web Awarding - List</potent>                                                                              <div course="pull-right">                                                                              <a (click)="create()"><span class="glyphicon glyphicon-plus"></span></a>                                                                              </div>                                                                              </div>                                                                              <ul class="list-group">                                                                              <li grade="list-group-detail" *ngFor="let person of personList">{{ person.firstname }} {{ person.lastname }}</li>                                                                              </ul>                                                                              </div>                                                            </div>                                                    

Well-nigh of the code above is from the Bootstrap documentation. Take annotation in particular the (click) event on the glyph icon in the panel heading. This will call the create part which will navigate us to the next page. Also annotation the following:

                                          <ul class="list-grouping">                                                                              <li class="list-grouping-item" *ngFor="allow person of personList">{{ person.firstname }} {{ person.lastname }}</li>                                                            </ul>                                                    

We are looping through the personList array and displaying the firstname and lastname properties.

Creating a Form for Saving Data

With the list page out of the way, allow'due south focus on the folio for creating our data.

Open the project's src/app/create/create.component.ts file and include the post-obit code:

                                          import { Component, OnInit } from '@angular/core';                                                            import { Location } from '@athwart/common';                                                                                                                        @Component({                                                                              moduleId: module.id,                                                                              selector: 'app-create',                                                                              templateUrl: 'create.component.html',                                                                              styleUrls: ['create.component.css']                                                            })                                                            export class CreateComponent implements OnInit {                                                                                                                                          public personList: Assortment<Object>;                                                                              public firstname: cord;                                                                              public lastname: string;                                                                                                                                          constructor(private location: Location) {                                                                              this.personList = localStorage.getItem("people") != null ? JSON.parse(localStorage.getItem("people")) : [];                                                                              this.firstname = "";                                                                              this.lastname = "";                                                                              }                                                                                                                                          ngOnInit() {}                                                                                                                                          salvage() {                                                                              if(this.firstname != "" && this.lastname != "") {                                                                              this.personList.push button({firstname: this.firstname, lastname: this.lastname});                                                                              localStorage.setItem("people", JSON.stringify(this.personList));                                                                              this.location.dorsum();                                                                              }                                                                              }                                                                                                                        }                                                    

Permit's break down what is happening in the above code.

Just like with the listing page, we are importing some Angular components and defining the HTML page that will be paired with our TypeScript lawmaking. We are defining three public variables that will exist bound to the UI for this particular folio.

                                          constructor(private location: Location) {                                                                              this.personList = localStorage.getItem("people") != null ? JSON.parse(localStorage.getItem("people")) : [];                                                                              this.firstname = "";                                                                              this.lastname = "";                                                            }                                                    

In the constructor method nosotros initialize our variables and pull any existing person data from local storage.

                                          salve() {                                                                              if(this.firstname != "" && this.lastname != "") {                                                                              this.personList.push({firstname: this.firstname, lastname: this.lastname});                                                                              localStorage.setItem("people", JSON.stringify(this.personList));                                                                              this.location.back();                                                                              }                                                            }                                                    

In the salvage method we check to make certain that the firstname and lastname variables are non empty. If this condition is met, we tin push a new object with them into the personList assortment and then re-save a serialized version of that array. When washed, we popular back in the navigation stack.

Now let's have a look at the HTML file that goes with this TypeScript code. Open the projection'southward src/app/create/create.component.html file and include the following markup:

                                          <div class="container">                                                                              <div course="panel panel-default">                                                                              <div grade="panel-heading">                                                                              <strong>Web Application - Create</strong>                                                                              <div course="pull-right">                                                                              <a (click)="save()"><span course="glyphicon glyphicon-floppy-disk"></span></a>                                                                              </div>                                                                              </div>                                                                              <div class="panel-body">                                                                              <form>                                                                              <div class="course-grouping">                                                                              <label for="firstname">First Name</label>                                                                              <input type="text" form="form-control" [(ngModel)]="firstname" id="firstname" placeholder="Get-go Name">                                                                              </div>                                                                              <div class="form-group">                                                                              <label for="lastname">Last Name</label>                                                                              <input blazon="text" class="grade-command" [(ngModel)]="lastname" id="lastname" placeholder="Final Name">                                                                              </div>                                                                              </form>                                                                              </div>                                                                              </div>                                                            </div>                                                    

Like with the listing folio we take a (click) event that calls a part. This time it calls the save function for saving our information and navigating dorsum in the stack. We likewise have the following in this detail HTML file:

                                          <form>                                                                              <div class="form-group">                                                                              <label for="firstname">First Name</label>                                                                              <input type="text" form="form-command" [(ngModel)]="firstname" id="firstname" placeholder="First Name">                                                                              </div>                                                                              <div class="form-grouping">                                                                              <label for="lastname">Last Name</label>                                                                              <input type="text" form="form-control" [(ngModel)]="lastname" id="lastname" placeholder="Last Name">                                                                              </div>                                                            </course>                                                    

Above nosotros have a form and each field has an [(ngModel)] tag. This is how we bind the firstname and lastname variables from our TypeScript file to the HTML file.

Bringing the Routes Together and Setting a Default Page Route

We have our two pages, merely they are not however connected to each other in the application. We also don't have any concept of a default folio withal.

Open the project'southward src/app/app.component.ts file and include the post-obit lawmaking:

                                          import { Component } from '@angular/cadre';                                                            import { ROUTER_DIRECTIVES } from "@angular/router";                                                                                                                        @Component({                                                                              moduleId: module.id,                                                                              selector: "app-root",                                                                              directives: [ROUTER_DIRECTIVES],                                                                              template: "<router-outlet></router-outlet>"                                                            })                                                            export course AppComponent { }                                                    

By including the code to a higher place we are proverb that we want this TypeScript file to act as our main routing outlet. All child page routes and components will flow through this file considering of the <router-outlet> tag.

Nonetheless, we don't have the routes configured.

Open the project'due south src/main.ts file and include the post-obit code:

                                          import { bootstrap } from '@athwart/platform-browser-dynamic';                                                            import { enableProdMode } from '@angular/core';                                                            import { provideRouter, RouterConfig } from '@angular/router';                                                            import { AppComponent, environment } from './app/';                                                                                                                        import { ListComponent } from './app/list/list.component';                                                            import { CreateComponent } from './app/create/create.component';                                                                                                                        if (surround.product) {                                                                              enableProdMode();                                                            }                                                                                                                        export const AppRoutes: RouterConfig = [                                                                              { path: "", component: ListComponent },                                                                              { path: "create", component: CreateComponent }                                                            ]                                                                                                                        bootstrap(AppComponent, [provideRouter(AppRoutes)]);                                                    

In the above code nosotros are importing every component we wish to link. When defining the routes, the road with the blank path is the default route. Finally we inject these routes when bootstrapping.

The Athwart web awarding should be consummate at this point. To come across it in activity, execute the following from your Command Prompt or Final:

If you're interested in seeing the total source code to the web awarding, you can download information technology here. Note there are a lot of files and directories that have been generated from the Angular CLI. Experience free to examine them, but they won't utilize for the NativeScript portion of this guide.

Converting to a NativeScript Mobile Application

Now nosotros're going to accept a wait at building the NativeScript equivalent of this web application. A few major differences to note between the two. First, we won't be using the Athwart CLI, simply instead the NativeScript CLI. Since NativeScript develops native applications at that place is no concept of local storage. Instead we'll exist using the very similar awarding-settings storage. It tin hands be switched out to use SQLite or Couchbase NoSQL.

With that said, let'south start by creating a new NativeScript project. From the Last (Mac and Linux) or Control Prompt (Windows), execute the following:

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

There are a few things to note near the above commands. By using the –ng tag we are using the Athwart NativeScript template. It operates on TypeScript which is what nosotros used in the web awarding. Besides note that if you're non using a Mac, yous cannot build for the iOS platform.

Nosotros need to add the component files to our project. The NativeScript CLI won't do this for us, but it isn't too troublesome to do this manually. Create the directories and files below:

                                          mkdir app/components                                                            mkdir app/components/list                                                            mkdir app/components/create                                                            touch on app/components/list/list.component.ts                                                            impact app/components/list/list.component.html                                                            bear on app/components/create/create.component.ts                                                            touch app/components/create/create.component.html                                                    

If you're using Windows, you won't have the mkdir and touch commands so you'll have to create these manually.

At present we can start developing the awarding!

Creating a List Component for Displaying a List of Information

Instead of picking and pulling from the spider web application, we're going to add our code and markup from scratch. Nevertheless, you'll discover much of what we do is near identical to the web application.

We're going to beginning with the TypeScript file of the list component. Open the projection's app/components/list/list.component.ts file and include the following lawmaking:

                                          import {Component} from "@angular/cadre";                                                            import {Router} from "@athwart/router";                                                            import {Location} from "@angular/common";                                                            import * every bit ApplicationSettings from "application-settings";                                                                                                                        @Component({                                                                              selector: "list",                                                                              templateUrl: "./components/list/listing.component.html",                                                            })                                                            export class ListComponent {                                                                                                                                          public personList: Array<Object>;                                                                                                                                          constructor(private router: Router, private location: Location) {                                                                              this.router = router;                                                                              this.personList = JSON.parse(ApplicationSettings.getString("people", "[]"));                                                                              this.location.subscribe((path) => {                                                                              this.personList = JSON.parse(ApplicationSettings.getString("people", "[]"));                                                                              });                                                                              }                                                                                                                                          create() {                                                                              this.router.navigate(["/create"]);                                                                              }                                                                                                                        }                                                    

Betwixt the web version and the NativeScript version of this file, things are very similar. This NativeScript version has a lot of things stripped out and the local storage has been replaced with application-settings, but beyond that I used the same code.

The core difference is in the UI that is bound to this TypeScript file. Open up the project's app/components/list/list.html file and include the post-obit markup:

                                          <ActionBar title="NativeScript - List">                                                                              <ActionItem text="Add" (tap)="create()" ios.position="correct"></ActionItem>                                                            </ActionBar>                                                            <GridLayout>                                                                              <ListView [items]="personList">                                                                              <template let-item="item">                                                                              <Label [text]="item.firstname + ' ' + particular.lastname"></Label>                                                                              </template>                                                                              </ListView>                                                            </GridLayout>                                                    

NativeScript does not return applications in a web view like other mobile frameworks so it doesn't understand HTML markup. Instead we must employ XML markup that NativeScript understands so it tin can be converted to native code at compile time.

In the in a higher place XML we are creating an action bar with a button for navigating us to the side by side component when we (tap) it. Notice instead of (click) we are using (tap) which isn't actually a big change.

The larger modify will be in how we loop through the array items. For the NativeScript ListView we don't make use of *ngFor but something else instead. Again, in the end, information technology isn't so far off from the web example.

Creating a Component for Saving User Defined Information

Permit'due south motility onto the second folio or component of our mobile application. Over again, you'll notice all the similarities between the Angular spider web application and the Angular NativeScript awarding.

Open the project's app/components/create/create.component.ts file and include the following code:

                                          import {Component} from "@angular/cadre";                                                            import {Location} from "@angular/common";                                                            import * as ApplicationSettings from "application-settings";                                                                                                                        @Component({                                                                              selector: "create",                                                                              templateUrl: "./components/create/create.component.html",                                                            })                                                            export class CreateComponent {                                                                                                                                          private personList: Array<Object>;                                                                              public firstname: string;                                                                              public lastname: string;                                                                                                                                          constructor(private location: Location) {                                                                              this.location = location;                                                                              this.personList = JSON.parse(ApplicationSettings.getString("people", "[]"));                                                                              this.firstname = "";                                                                              this.lastname = "";                                                                              }                                                                                                                                          save() {                                                                              if(this.firstname != "" && this.lastname != "") {                                                                              this.personList.push({firstname: this.firstname, lastname: this.lastname});                                                                              ApplicationSettings.setString("people", JSON.stringify(this.personList));                                                                              this.location.back();                                                                              }                                                                              }                                                                                                                        }                                                    

Like with the list component nosotros are importing the necessary Angular and NativeScript components. We are also defining what XML file to be paired with this particular TypeScript file.

The CreateComponent itself is pretty much identical to that of the web awarding version. The but exception being its use of application-settings rather than local storage.

Now let'south expect at the XML layout to go with this TypeScript file. Open the project'southward app/components/create/create.html file and include the following markup:

                                          <ActionBar championship="NativeScript - Create">                                                                              <NavigationButton text="Back" ios.position="left"></NavigationButton>                                                                              <ActionItem text="Save" (tap)="save()" ios.position="correct"></ActionItem>                                                            </ActionBar>                                                            <StackLayout>                                                                              <TextField hint="Beginning Proper noun" [(ngModel)]="firstname"></TextField>                                                                              <TextField hint="Concluding Proper noun" [(ngModel)]="lastname"></TextField>                                                            </StackLayout>                                                    

It is very different than the HTML spider web version, over again considering NativeScript doesn't sympathise common HTML.

Here we have an action bar with two buttons. iOS doesn't have a back button then we need to define it. We as well create a button for triggering the save office when it is tapped.

When it comes to our course, nosotros have two TextField items, both bound to our TypeScript file with the [(ngModel)] tag.

Configuring the Application Routes

We take our two components created, but they are not integrated with our application even so. We need to ready the routing in a like style to what was done in the spider web application.

Open the project'due south app/app.component.ts file and include the following code:

                                          import {Component} from "@angular/cadre";                                                            import {NS_ROUTER_DIRECTIVES} from "nativescript-angular/router";                                                                                                                        @Component({                                                                              selector: "my-app",                                                                              directives: [NS_ROUTER_DIRECTIVES],                                                                              template: "<page-router-outlet></folio-router-outlet>"                                                            })                                                            export class AppComponent {                                                                                                                        }                                                    

A few things to notation in this file.

We're adding the routing outlet and the NativeScript router directives. This file volition human activity every bit a driver to each page of our awarding.

Adjacent we need to define the actual awarding routes. Instead of doing this in the app/app.component.ts file nosotros are going to dispense the app/chief.ts file. Open it and include the following lawmaking:

                                          import {nativeScriptBootstrap} from "nativescript-angular/application";                                                            import {nsProvideRouter} from "nativescript-angular/router";                                                            import {RouterConfig} from "@angular/router";                                                            import {AppComponent} from "./app.component";                                                                                                                        import {ListComponent} from "./components/listing/listing.component";                                                            import {CreateComponent} from "./components/create/create.component";                                                                                                                                                                                    export const AppRoutes: RouterConfig = [                                                                              { path: "", component: ListComponent },                                                                              { path: "create", component: CreateComponent }                                                            ];                                                                                                                        nativeScriptBootstrap(AppComponent, [[nsProvideRouter(AppRoutes, {})]]);                                                    

In this file we are keeping the foundation bootstrap logic that already existed, simply we are likewise including an assortment of awarding routes to be injected into the bootstrap. The routes are injected with the nsProvideRouter component.

At this bespeak our application is consummate and tin be launched. If you'd like to see the total source code to this project, it can be downloaded here.

Conclusion

We just saw how to catechumen an Athwart web application to a NativeScript Android and iOS mobile application. At that place are a few key points I'd like to brand almost what we but accomplished. In the web application we used Bootstrap for our styling considering I'm not much of a designer. The Bootstrap UIs were created with HTML, something a spider web browser can understand. Since NativeScript uses native lawmaking and doesn't sympathize HTML, we have to use XML components. This is the core deviation betwixt spider web and mobile. The TypeScript code was near identical betwixt the web and NativeScript versions.

Building a web application from Angular makes things very easy for united states of america when we endeavour to catechumen the code to mobile. Since Athwart doesn't rely on the DOM, native frameworks like NativeScript tin can really polish.

Nic Raboy

Nic Raboy

Nic Raboy is an abet of modernistic web and mobile development technologies. He has feel in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

How to Build Android App With Angular

Posted by: matthewsmaraver1971.blogspot.com