Mobile
Article

Building a Native App with JavaScript Using NativeScript

By Jay Raj

There are many options available for utilizing HTML, CSS and JavaScript to create cross platform applications and I have covered many of them before. In this article I will look at NativeScript from Telerik that claims to be easier to create for cross platform apps than many existing options.

From their official documentation.

NativeScript enables developers to build native apps for iOS, Android and Windows Universal while sharing the application code across the platforms. When building the application UI, developers use our libraries, which abstract the differences between the native platforms.

Creating an image search flicker app

In this tutorial we will create a simple app that searches for images on flickr and displays the results. We will make use of the flicker developer API to search images.

Source code from this tutorial is available on GitHub.

Getting Started

Install nodejs and then using the node package manager (npm), install native script.

npm install -g nativescript

After installing native script, create a new project called NativeApp.

tns create NativeApp

Navigate to the project directory and add the mobile development platform.

tns platform add android

Run the application on the android emulator.

tns run android --emulator
NativeApp default preview

Project Structure

Project Structure

Inside the project folder there are 3 sub-folders: app, lib and platforms. The application source code resides in the app folder. Application code is written using JavaScript and the user interface designed using XML.

Inside the app folder is a file called main-page.xml which has the default user interface code. In main-view-model.js is the default model code and main-page.js defines the application logic. Finally app.js contains the code to start the application with the defined modules.

Designing the app

Let’s start by designing the app using XML. Open main-page.xml and look at the default code. Remove everything except the page tag. The Page tag has an attribute called loaded which executes the pageLoaded function once the app loads. The pageLoaded function is inside the main-page.js file.

This project will use a stack layout to design our app. There are a number of layouts offered by native script.

Inside the Page tag add the stack layout.

<StackLayout orientation="vertical">

</StackLayout>

Define the stack layout with a vertical orientation. Add a search text box and button inside the stack layout.

<TextField width="300px" hint="search keyword" />

<Button text="Search" height="50px" style="background-color:green;width:300px;border:none;font-size:20px;" />

Save changes and run the app. It should look something like the below.

App Preview

Fetching data from flickr

Add an attribute called tap to the search button.

tap="signin"

Now, when the user taps the search button the signin function is called. Let’s define the signin function inside main-page.js.

exports.signin = function() {
  // Code would be here !
};

To use flickr’s developer APIs you will need a free account on flickr. Request an API key to make API requests.

In main-page.js define the API key.

var api_key = 'replacewithyourkey';

Calling the API will require the http module, so import the module into main-page.js.

var http = require("http");

Inside the signin function, and using the http module, now make the API call.

http.getJSON("https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=" + api_key + "&text=hello&format=json&nojsoncallback=1&per_page=5").then(function(r) {

    console.log(JSON.stringify(r));

}, function(e) {

    console.log(e);

});

The code above makes the API call with the search text hard coded for now, this will become dynamic later in the tutorial.

When running an app in the emulator you will need to run ‘adb logcat’ to check log messages.

Save changes and run the app on the emulator. Click the search button and the returned result from Flickr should be visible in terminal.

Next create the image url using the response returned and push the URL to the images array.

An observable array is required to create and detect changes to a collection of things. Bind this same observable array to the view so that the view updates whenever a change occurs.

To create the observable array, add these variable declarations to main-page.js :

var observableArray = require("data/observable-array");
var images = new observableArray.ObservableArray([]);

Based on the response returned from the API request, the next task is to create the flickr image URL. Detailed information can be found here about creating flickr URLs.

Next, we iterate through the returned data, create the image URLs and push to the images array. Add this code inside the signin function.

var imgUrl = '';

var photoList = r.photos.photo;

for (var i = 0; i < photoList.length; i++) {
    imgUrl = "https://farm" + photoList[i].farm + ".staticflickr.com/" + photoList[i].server + "/" + photoList[i].id + "_" + photoList[i].secret + ".jpg";

    images.push({
        img: imgUrl
    });

}

Binding data to the UI

Once the data is in the images array, bind it to the UI. For displaying the data, create a ListView in main-page.xml, underneath the existing Button element.

<ListView>
    <ListView.itemTemplate>

        <Image stretch="fill" height="200px" />

    </ListView.itemTemplate>
</ListView>

Bind the images array to the list view and set the source of the image.

<ListView items="{{ images }}">
    <ListView.itemTemplate>

        <Image stretch="fill" height="200px" src="{{img}}" />

    </ListView.itemTemplate>
</ListView>

For the images array to be available across the view, set the images array in the observable module. Do this by importing an observable module and using it to create an observable object.

var observableModule = require("data/observable");
var pageData = new observableModule.Observable();

In the pageLoaded function, set the images array to the observable module and add the observable module to the page context.

function pageLoaded(args) {
    var page = args.object;
    pageData.set("images", images);
    page.bindingContext = pageData;
}

Using the same pageData observable object, the values from the search text box are readable. Modify the text field to add the text attribute.

<TextField width="300px" text="{{txtKeyword}}"  hint="search keyword"/>

Inside the signin function, remove the hard coded hello search text and replace it with:

pageData.get('txtKeyword')

Save changes and run the app on the emulator. Click on the search button and images received from the Flickr API should be viewable. The request is for 5 images, so scrolling down should show all the images.

Images loaded from Flickr

Conclusion

This tutorial demonstrates how to get started using NativeScript to create a simple mobile app. For detailed information about using NativeScript, I would recommend reading the official documentation.

Do you have had any mobile development experience using NativeScript? What’s your opinion about using NativeScript ? Let us know your thoughts, suggestions and corrections in the comments below.

  • Evan Wieland

    Hey great article Jay!! I love NS and think it’s great how much attention it’s getting. Keep up the great work!

    • Jay

      Thanks for the feedback @evanwieland:disqus . Glad you liked it.

  • WooDzu

    Very interesting. Is there a reason NOT to use it for mobile app development?

    • Jay

      Well, I just started with NativeScript and haven’t been with it enough to find any disadvantages, as of yet. Would love to know your thoughts if you have used it.

      • Evan Wieland

        The lack of css properties supported can bring you to tears at times :(

        • Jay

          Thanks for the info @evanwieland:disqus

        • Hey Evan,

          I work for Telerik with the NativeScript team. We’re planning on adding a new batch of CSS properties in our upcoming 1.2 release, see https://github.com/NativeScript/NativeScript/issues/191. Please let us know if there are any properties you’d like to use that aren’t on this list. There are some properties that don’t really translate to native iOS and Android layouts, but we want to do the best we can.

      • Chris Ward

        Yes, Telerik have quite a good history, so this could be a great framework if all you want is mobile apps and not mobile optimised web sites to. I am looking forward to trying it more to.

  • Evan Wieland

    Hey TJ! Yeah I know your involvement with NS :) I watch all the webcasts and blog articles you have (thanks for those btw). I’m glad the css support is expanding. Are @keyframes going to ever make an appearance you think?

    • Hey Evan,

      Awesome :) Feel free to comment about @keyframes in the GitHub issue if you think it would be valuable. There’s a separate discussion about how to handle animations in NativeScript which is being covered by this issue: https://github.com/NativeScript/NativeScript/issues/255. What the final version of that is going to look like is still being decided so we’re definitely open to feedback.

  • is there any visual IDE for the design?

    • Chris Ward

      I don’t think so, but as it’s XML there may be something more general available?

  • OZ

    Hay there, nice article, but there is one thing missing, for anybody that want to really try it. In “Getting Started” section maybe add how to install and configure Apache Ant.

  • John Samilin

    Why should I choose Native Script and not Appcelerator Titanium?

    • Chris Ward

      Appcelerator Titanium uses it’s own language, which is JavaScript like, but still an extra learning curve.

  • Sonu

    So my question related to performance

    NativeScript == Java ?

    • Chris Ward

      I think I will have to give a generic programming response and say “It depends”. For a start this only applies to Android, but yes, it depends what you’re programming really.

  • Neeraj Shah

    can i build transaction based android app via use of NativeScript 2.0?

    • Chris Ward

      What do you mean? An App that lists transactions, an app that use transactional processing?

  • Michael Howard

    Any updates. I am thinking about developing an app using this tool. The limitations matter, so I am trying to figure out the gotchas before I go too far.

    • Chris Ward

      Any updates on what @disqus_5z8hJNQe6c:disqus ?

  • Bineesh Thavanur

    This is quite interesting and give new hopes. Will you like if i do a video of this using a web view experience plus audio comment for youtube ?

Recommended
Sponsors
Get the latest in Mobile, once a week, for free.