{"action":"created","comment":{"url":"https://api.github.com/repos/NativeScript/docs/pulls/comments/38301999","id":38301999,"diff_hunk":"@@ -1,51 +1,1586 @@\n ---\n-nav-title: \"Getting Started with NativeScript\"\n-title: \"Getting Started\"\n-description: \"Learn the basics of of how NativeScript work, how to set up your system and how to create your first Hello World app\"\n+nav-title: \"Getting Started Guide\"\n+title: \"Getting Started Guide\"\n+description: \"Learn the basics of how NativeScript works, how to set up your system, and how to create your first app\"\n position: 2\n+guide: true\n ---\n \n-# Getting Started\n+## NativeScript Getting Started Guide\n \n-NativeScript strips the complexity from native development both in terms of required coding skills and system setup. \n+Welcome to the [NativeScript](https://nativescript.org) getting started guide. In this guided tutorial you'll use NativeScript, a cross-platform JavaScript framework for building native mobile apps, to build an iOS and Android app from scratch.\n \n-To get started, you need JavaScript or TypeScript knowledge to implement your business logic, XML and CSS knowledge to design your UI and an idea for a mobile app. You do not need Java or Objective-C knowledge.\n+> **TIP:** For a video introduction to NativeScript, see the [getting started guide on YouTube](https://www.youtube.com/watch?v=rsCT5fpES4Q).\n \n-Once you have your app idea, you can get started in a few minutes.\n+## What you're building\n \n-<iframe width=\"640\" height=\"360\" src=\"https://www.youtube.com/embed/rsCT5fpES4Q?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n+This guide will walk you through building [Groceries](https://github.com/NativeScript/sample-Groceries), a groceries management app that does the following things:\n \n-You can find more details about each step of the setup and project creation process below and at the referenced pages of the documentation.\n+- Connects to an existing RESTful service.\n+- Lets users to register and login.\n+- Lets authenticated users to add and delete groceries from a list.\n+- Runs cross-platform (iOS and Android).\n \n-### 1. Choose your tools and **[set up your system](setup/quick-setup.md)**.\n+If you follow along to the end, here's what the finished app will look like on iOS:\n \n-If you are familiar with the Cordova CLI or if you want to develop and build your apps locally and free of charge, you can set up your system with the **NativeScript CLI**.\n-\t\n-* [Windows setup](setup/ns-cli-setup/ns-setup-win.md)\n-* [OS X setup](setup/ns-cli-setup/ns-setup-os-x.md)\n-* [Linux setup](setup/ns-cli-setup/ns-setup-linux.md)\n+![login](img/cli-getting-started/chapter0/ios/1.png)\n+![register](img/cli-getting-started/chapter0/ios/2.png)\n+![list](img/cli-getting-started/chapter0/ios/3.png)\n \n-If you prefer to concentrate on development and build your apps with a third-party build service, you can use the [Telerik AppBuilder tools](setup/ab-setup/ab-web-setup.md).\n-\t\n-* [In-browser IDE](setup/ab-setup/ab-web-setup.md)\n-* [Windows IDE](setup/ab-setup/ab-win-setup.md)\n-* [Extension for Visual Studio](setup/ab-setup/ab-vse-setup.md)\n-* [CLI](setup/ab-setup/ab-cli-setup.md)\n+And here's what the app will look like on Android:\n \n-### 2. Go through the **Hello World** tutorial for your preferred tool set.\n+![](img/cli-getting-started/chapter0/android/1.png)\n+![](img/cli-getting-started/chapter0/android/2.png)\n+![](img/cli-getting-started/chapter0/android/3.png)\n \n-This quick start development guide will introduce you to the basic architecture of a NativeScript app, data binding and how to implement user interfaces and styling.\n \n-* [Hello World from the NativeScript CLI](hello-world/hello-world-ns-cli.md)\n-* [Hello World from AppBuilder](hello-world/hello-world-appbuilder.md)\n+## Getting up and running\n \n-### 3. Learn from the full app samples prepared by the NativeScript team.\n+In this chapter you're going to start with the basics, including installing the NativeScript CLI, starting a new project, and getting your first app up and running.\n \n-[Sample apps with open source code](samples.md)\n+### Install NativeScript and configure your environment\n \n-### 4. Explore the **[modules overview](modules.md)** and the **[API Reference](ApiReference/application/README.md)**.\n+The NativeScript CLI has a few system requirements you must have in place before building NativeScript apps. As a first step, start by going through the instructions for your operating system:\n \n-The extensive overview and API reference will introduce to the how-tos of NativeScript development. You will learn how to tap into the native capabilities that you want to implement inside your app.\n+- [Windows](http://docs.nativescript.org/setup/ns-cli-setup/ns-setup-win.html)\n+- [OS X](http://docs.nativescript.org/setup/ns-cli-setup/ns-setup-os-x.html)\n+- [Linux](http://docs.nativescript.org/setup/ns-cli-setup/ns-setup-linux.html)\n \n-# Remarks\n-If you hit some unexpected behavior please check the [Troubleshooting](./troubleshooting.md) article.\n+> **TIP**: If you're a bit overwhelmed by these requirements, or if you're looking for a way to build iOS apps on Windows, you might be interested in [using NativeScript with Telerik AppBuilder](http://docs.nativescript.org/setup/quick-setup#the-appbuilder-tool-set). Telerik AppBuilder provides tooling for NativeScript apps, including the ability to perform iOS and Android builds in the cloud, which removes the need to complete these system requirements.\n+\n+After completing the setup you should have two commands available from your terminal: `tns`—which is short for **T**elerik **N**ative**S**cript—and `nativescript`. The two commands are equivalent, so we'll stick with the shorter `tns`.\n+\n+You can verify the installation was successful by running `tns` in your terminal. You should see something like this:\n+\n+```\n+$ tns\n+# NativeScript\n+┌─────────┬─────────────────────────────────────────────────────────────────────┐\n+│ Usage   │ Synopsis                                                            │\n+│ General │ $ tns <Command> [Command Parameters] [--command <Options>]          │\n+│ Alias   │ $ nativescript <Command> [Command Parameters] [--command <Options>] │\n+└─────────┴─────────────────────────────────────────────────────────────────────┘\n+```\n+\n+### Start your app\n+\n+With the NativeScript CLI installed, it's time to start building your app. Normally, you would [use the `tns create` command to create an empty NativeScript application](https://github.com/NativeScript/NativeScript-cli#create-project). For this guide, we've scaffolded out a boilerplate project to act as a starting point for [Groceries](https://github.com/NativeScript/sample-Groceries).\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Get the Groceries starting point\n+</h4>\n+\n+Navigate to a folder where you want to keep your app code:\n+\n+<div class=\"no-copy-button\"></div>\n+\n+```\n+cd the-folder-you-want-groceries-to-be-in\n+```\n+\n+Next, assuming you have [git installed](http://www.git-scm.com/), clone the Groceries repo from GitHub:\n+\n+```\n+git clone https://github.com/NativeScript/sample-Groceries.git\n+```\n+\n+After that, change into the newly cloned repo's folder:\n+\n+```\n+cd sample-Groceries\n+```\n+\n+The master branch has the final state of the Groceries app. Feel free to [refer back to it](https://github.com/NativeScript/sample-Groceries) at any time, but for now, switch over to the “start” branch for this guide's starting point:\n+\n+```\n+git checkout start\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+### Add target development platforms\n+\n+Your app is now set up, but before you run it, you need to initialize a platform-specific native project for each platform you intend to target.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add the iOS and Android platforms\n+</h4>\n+\n+If you're on a Mac, start by adding the iOS platform:\n+\n+```\n+tns platform add ios\n+```\n+\n+Next, add the Android platform with the same `platform add` command:\n+\n+```\n+tns platform add android\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+>**NOTE:** You can add platforms only for SDKs that you already have installed on your development machine. If you get errors running `tns platform add`, refer back to the section on [setting up your development environment](#install-nativescript-and-configure-your-environment).\n+\n+The `platform add` command adds a folder called `platforms` to your project, and copies all of the required native SDKs into this folder. When you build the application, the NativeScript CLI will copy your application code into the `platforms` folder so that a native binary can be created.\n+\n+### Running your app\n+\n+With the platform initialization complete, you can now run your app in an emulator or on devices.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Run your app\n+</h4>\n+\n+If you're on a Mac, start by running the app in an iOS simulator with the following command:\n+\n+```\n+tns run ios --emulator\n+```\n+\n+If all went well, you should see something like this:\n+\n+![iOS login](img/cli-getting-started/chapter1/ios/1.png)\n+\n+Next, run your app on an Android emulator with the following command:\n+\n+```\n+tns run android --emulator\n+```\n+\n+> **WARNING**:\n+> * You must have at least one Android AVD (Android Virtual Device) configured for this command to work. If you get an error, try [setting up an AVD](https://www.genymotion.com/#!/) and then run the command again.\n+> * If you're using Genymotion, launch your Genymotion virtual device, and then run `tns run android --emulator --geny`. \n+\n+If all went well, you should see your app running in an Android emulator:\n+\n+![Android login](img/cli-getting-started/chapter1/android/1.png)\n+\n+<div class=\"exercise-end\"></div>\n+\n+Here are a few other tips for running NativeScript apps.\n+\n+> **TIP**:\n+> * To run on a USB-connected Android or iOS device, use the same `run` command without the `--emulator` flag—i.e. `tns run android` and `tns run ios`.\n+> * The `tns device` command lists all USB-connected iOS devices, USB-connected Android devices, and Genymotion virtual devices that `tns run` can deploy to. Note that `tns device` does not list iOS simulators or Android AVDs.\n+\n+### Development workflow\n+\n+At this point, you have the NativeScript CLI downloaded and installed, as well as the iOS and Android dependencies that you need to run your app. Now you need a good workflow that lets you make changes and see results fast.\n+\n+The simplest way to see your changes is to execute `tns run ios` or `tns run android` after you save files. To see this action, let's make a trivial update to your app.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Your first NativeScript change\n+</h4>\n+\n+If your previous `tns run ios` or `tns run android` task is still running, type `Ctrl+C` in your terminal to kill it.\n+\n+Open your app's `app/views/login/login.xml` file in your text editor of choice and change `<Label text=\"hello world\" />` to `<Label text=\"hello NativeScript\" />`.\n+\n+Return to your terminal and run either `tns run ios --emulator` (if you're on a Mac), or `tns run android --emulator`. You should see the app relaunch and the updated text displayed.\n+\n+<div class=\"exercise-end\"></div>\n+\n+As you might have noticed, the `tns run` command blocks your terminal while your app is running (it's the task you had to use `Ctrl` + `C` to kill). The `tns run` command sticks around because the task is a console of sorts. The task shows both the output of `console.log()` statements as your app executes, as well as stack traces when things go wrong. So if your app crashes at any time during this guide, look to the terminal for a detailed report of the problem.\n+\n+The iOS and Android logs can be a bit noisy, so you might have to scroll up a bit to find the actual problem. For example if I try to call `foo.bar()` when `foo` does not exist, here's the pertinent information I get on iOS:\n+\n+```\n+/app/path/to/file.js:14:8: JS ERROR ReferenceError: Can't find variable: foo\n+1   0xe3dc0 NativeScript::FFICallback<NativeScript::ObjCMethodCallback>::ffiClosureCallback(ffi_cif*, void*, void**, void*)\n+```\n+\n+And here's the same information in the Android logs:\n+\n+```\n+E/TNS.Native( 2063): ReferenceError: foo is not defined\n+E/TNS.Native( 2063): File: \"/data/data/org.nativescript.groceries/files/app/./views/login/login.js, line: 13, column: 4\n+```\n+\n+> **TIP**: When you're trying to debug a problem, you can also try adding `console.log()` statements in your JavaScript code—exactly as you would in a browser-based application.\n+\n+If you find continuously running `tns run` from the terminal to be tedious, you may be interested in trying one of the following workflows:\n+\n+* The `tns livesync` command instantly transfers XML, CSS, and JavaScript files to a running NativeScript app. If you set the command's `--watch` flag (`tns livesync ios --emulator --watch` or `tns livesync android --emulator --watch`), the NativeScript CLI will watch your app for changes, and apply those changes automatically after you save files. Be warned, however, that the `livesync` command currently does not show `console.log()` output or stack traces. So during debugging you may want to switch back to `tns run`.\n+* For Sublime Text users, [this build script](http://developer.telerik.com/featured/a-nativescript-development-workflow-for-sublime-text/) lets you type `Cmd`/`Ctrl` + `B` to start a build without returning to the terminal. (This is the workflow used for this guide.)\n+* Emil Öberg's [nativescript-emulator-reload npm module](https://github.com/emiloberg/nativescript-emulator-reload) adds a Gulp watcher that relaunches the emulator after every change you make.\n+\n+Now that you have created an app, configured your environment, and set up your app to run on iOS and Android, you're ready to start digging into code.\n+\n+## Building the UI\n+\n+Before you start coding the Groceries app it's important to understand a NativeScript app's folder structure. It'll help you understand where to place new files, as well as a bit of what's going on with NativeScript under the hood.\n+\n+Go ahead and open your app's `sample-Groceries` folder in your text editor of choice and let's dig in.\n+\n+### Directory structure\n+\n+To keep things simple, let's start by looking at the outer structure of the Groceries app:\n+\n+```\n+.\n+└── sample-Groceries\n+    ├── app\n+    │   └── ...\n+    ├── package.json\n+    └── platforms\n+        ├── android\n+        └── ios\n+```\n+\n+Here's what these various files and folders do:\n+\n+- **app**: This folder contains all the development resources you need to build your app. You'll be spending most of your time editing the files in here.\n+- **package.json**: This file contains your app's configuration details, such as your app id, the version of NativeScript you're using, and also which npm modules your app uses. We'll take a closer look at how to use this file when we talk about using npm modules in [chapter 5](#plugins-and-npm-modules).\n+- **platforms**: This folder contains the platform-specific code NativeScript needs to build native iOS and Android apps. For example in the `android` folder you'll find things like your project's `AndroidManifest.xml` and .apk executable files. Similarly, the `ios` folder contains the Groceries' Xcode project and .ipa executables.\n+\n+The NativeScript CLI manages the `platforms` folder for you as you develop and run your app; therefore it's a best practice to treat the `platforms` folder as generated code. The Groceries app includes the `platforms` folder in its `.gitignore` to exclude its files from source control.\n+\n+Next, let's dig into the `app` folder, as that's where you'll be spending the majority of your time.\n+\n+```\n+.\n+└── sample-Groceries\n+    ├── app\n+    │   ├── App_Resources\n+    │   │   ├── Android\n+    │   │   └── iOS\n+    │   ├── shared\n+    │   │   └── ...\n+    │   ├── tns_modules\n+    │   │   └── ...\n+    │   ├── views\n+    │   │   └── login\n+    │   │       ├── login.js\n+    │   │       └── login.xml\n+    │   ├── app.css\n+    │   ├── app.js\n+    │   └── ...\n+    └── ...\n+```\n+Here's what these various files and folders do:\n+\n+- **App_Resources**: This folder contains platform-specific resources such as icons, splash screens, and configuration files. The NativeScript CLI takes care of injecting these resources into the appropriate places in the `platforms` folder when you execute `tns run`.\n+- **shared**: This folder, specific to the Groceries app, contains any files you need to share across views in your app. In the Groceries app, you'll find a few view model objects and a `config.js` file used to share configuration variables like API keys.\n+- **tns_modules**: This folder contains the NativeScript-provided modules you'll use to build your app. Each module contains the platform-specific code needed to implement some feature—the camera, http calls, the file system, and so forth—exposed through a platform-agnostic API (e.g. `http.getJSON()`). We'll look at some examples momentarily.\n+- **views**: This folder contains the code to build your app's views, each of which will have a subfolder in `views`. Each view is made up of an XML file, a JavaScript file, and an optional CSS file. The groceries app contains three folders for its three views.\n+- **app.css**: This file contains global styles for your app. We'll dig into app styling in [section 2.3](#css).\n+- **app.js**: This file sets up your application's starting module and initializes the app.\n+\n+Let's start with `app/app.js`, as it's the starting point for NativeScript apps. Your `app.js` contains the three lines below: \n+\n+``` JavaScript\n+var applicationModule = require(\"application\");\n+applicationModule.mainModule = \"./views/login/login\";\n+applicationModule.start();\n+```\n+\n+Here, you're requiring, or importing, the [NativeScript application module](http://docs.nativescript.org/ApiReference/application/HOW-TO). Then, you set its `mainModule`, or the starting screen of your app to be the login screen, which lives in your app's `views/login` folder.\n+\n+> **TIP**: JavaScript modules in NativeScript follow the [CommonJS specification](http://wiki.commonjs.org/wiki/CommonJS). This means you can use the [`require()` method](http://wiki.commonjs.org/wiki/Modules/1.1#Module_Context) to import modules, as is done above, as well as use the `export` keyword to expose a module's properties and methods, which we'll look at later in this chapter. These are the same constructs Node.js uses for JavaScript modules, so if you already know how to use Node.js modules, you already know how to use NativeScript modules.\n+\n+Now that your app is ready for development, let's add some UI components to make your login screen show more than some basic text.\n+\n+### Adding UI components\n+\n+Let's dig into the files used to create your app's UI, which reside in the `app/views` folder. Each folder in `app/views` contains the code for one of the three pages in Groceries: `list`, `login`, and `register`. If you look in the `app/views/login` folder, you'll see three files: `login.css`, `login.js`, and the `login.xml` file we updated in the previous chapter. When you open `login.xml` again you should see the following code:\n+\n+``` XML\n+<Page>\n+    <Label text=\"hello NativeScript\" />\n+</Page>\n+```\n+\n+This page currently contains two UI components: a `<Page>` and a `<Label>`. To make this page look more like a login page, let's add a few additional components, namely two `<TextField>` elements and two `<Button>` elements.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add UI components to <code>login.xml</code>\n+</h4>\n+\n+Open `app/views/login/login.xml` and replace the existing `<Label>` with the following code:\n+\n+``` XML\n+<TextField hint=\"Email Address\" keyboardType=\"email\" />\n+<TextField secure=\"true\" hint=\"Password\" />\n+\n+<Button text=\"Sign in\" />\n+<Button text=\"Sign up for Groceries\" />\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+NativeScript UI components provide attributes to let you configure their behavior and appearance. The code you just added uses the following attributes:\n+\n+- `<TextField>`\n+    - `hint`: Used to show placeholder text in the TextField to tell the user what to type.\n+    - `secure`: A boolean attribute that determines whether the TextField's text should be masked, which is commonly done on password fields.\n+    - `keyboardType`: The type of keyboard to present to the user for input. In this case, `keyboardType=\"email\"` shows a keyboard optimized for entering email addresses. NativeScript currently supports [five types of keyboards](http://docs.nativescript.org/ApiReference/ui/enums/KeyboardType/README) for text fields.\n+- `<Button>`\n+    - `text`: Controls the text displayed within the button.\n+\n+After you [run your app](#development-workflow) with this change, you will see a single `<Button>` component on the screen:\n+\n+![login 1](img/cli-getting-started/chapter2/ios/1.png)\n+![login 1](img/cli-getting-started/chapter2/android/1.png)\n+\n+You need to tell NativeScript how to layout the UI components in your page. Let's look at how to use NativeScript layouts to arrange these components on the screen.\n+\n+> **TIP**: The NativeScript docs include a [full list of the UI components and attributes](http://docs.nativescript.org/ui-with-xml) with which you can build your apps. You can even [build your own, custom UI components](https://docs.nativescript.org/ui-with-xml#custom-components).\n+\n+### Layouts \n+\n+NativeScript provides several different layout containers that allow you to place UI components precisely where you want them to appear. \n+\n+- The [Absolute Layout](https://docs.nativescript.org/ApiReference/ui/layouts/absolute-layout/HOW-TO.html) lets you position elements using explicit x and y coordinates. This is useful when you need to place elements in exact locations, for example showing an activity indicator widget in the top-left corner of your app.\n+- The [Dock Layout](https://docs.nativescript.org/ApiReference/ui/layouts/dock-layout/HOW-TO.html) is useful for placing UI elements at the outer edges of your app. For example, a container docked at the bottom of the screen would be a good location for an ad.\n+- The [Grid Layout](https://docs.nativescript.org/ApiReference/ui/layouts/grid-layout/HOW-TO.html) lets you divide your interface into a series of rows and columns, much like a `<table>` in HTML markup.\n+- The [Stack Layout](https://docs.nativescript.org/ApiReference/ui/layouts/stack-layout/HOW-TO.html) lets you stack child UI components either vertically or horizontally.\n+- The [Wrap Layout](https://docs.nativescript.org/ApiReference/ui/layouts/wrap-layout/HOW-TO.html) allows child UI components to flow from one row or column to the next when space is filled.\n+\n+For your login screen, all you need is a simple `<StackLayout>` to stack the UI components on top of each other. In later sections, you'll use some of the more advanced layouts.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add a stack layout to the login screen\n+</h4>\n+\n+In `login.xml`, add the `<StackLayout>` component below directly within the `<Page>` component. `login.xml` should look like this:\n+\n+``` XML\n+<Page>\n+    <StackLayout orientation=\"vertical\">\n+\n+        <TextField hint=\"Email Address\" keyboardType=\"email\" />\n+        <TextField secure=\"true\" hint=\"Password\" />\n+\n+        <Button text=\"Sign in\" />\n+        <Button text=\"Sign up for Groceries\" />\n+\n+    </StackLayout>\n+</Page>\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+The stack layout is a UI component, and as such, it has attributes just like the `<TextField>` and `<Button>` components you used in the previous section. Here, the `orientation=\"vertical\"` attribute tells the stack layout to arrange its child components vertically.\n+\n+After you run your app with this change, you'll see that your login page's UI components now stack up:\n+\n+![login 2](img/cli-getting-started/chapter2/ios/2.png)\n+![login 2](img/cli-getting-started/chapter2/android/2.png)\n+\n+Although the UI components are in the correct order, they could use some spacing and a bit of color to make the app look a bit nicer. To do that let's look at another NativeScript feature: CSS.\n+\n+> **TIP**:\n+> * For a simple introduction to the other NativeScript layout elements, check out Jen Looper's article on [demystifying NativeScript layouts](https://www.nativescript.org/blog/demystifying-nativescript-layouts).\n+> * Refer to the NativeScript docs for a [more detailed look at how NativeScript layouts work](http://docs.nativescript.org/layouts) and the various things you can do to configure them.\n+\n+### CSS\n+\n+NativeScript uses a [subset of CSS](http://docs.nativescript.org/styling) to change the visual appearance of your app. You can use three mechanisms to add CSS properties to UI components: [application-wide CSS](http://docs.nativescript.org/styling#application-wide-css) (`app.css`), [page-specific CSS](http://docs.nativescript.org/styling#page-specific-css), and an [inline `style` attribute](http://docs.nativescript.org/styling#inline-css).\n+\n+> **TIP**:\n+> * Place CSS rules that should apply to all pages in your `app.css`, and CSS rules that apply to a single page in a page-specific CSS file (e.g. `login.css`). \n+> * Although inline styles are great for quick testing—e.g. `<Page style=\"background-color: green;\">` you should avoid them in general because the `style` attributes tend to clutter up XML files especially if/when you need to apply multiple rules.\n+\n+Let's start by adding a few application-wide CSS rules.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Create global styles\n+</h4>\n+\n+Paste the following code in `app.css` file:\n+\n+``` CSS\n+Page {\n+    background-color: white;\n+    font-size: 17;\n+}\n+TextField {\n+    margin: 10;\n+    padding: 10;\n+}\n+Image {\n+    margin-top: 20;\n+    margin-left: 0;\n+    margin-right: 0;\n+    margin-bottom: 80;\n+}\n+Button {\n+    margin: 10;\n+    padding: 10;\n+}\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+If you've done any web development before, the syntax should feel familiar here. You select four UI components (Page, TextField, Image, and Button) by their tag name, and then apply a handful of CSS rules as name/value pairs. NativeScript does not support all CSS properties because it is not possible to replicate some of them in native apps without causing performance issues. A [full list of the CSS properties that are supported](http://docs.nativescript.org/styling#supported-properties) are listed in the NativeScript docs.\n+\n+Let's make one more change. Although oftentimes you want CSS rules to apply equally to your iOS and Android app, occasionally it makes sense to apply a CSS rule to only one platform. For example, iOS text fields frequently have borders around them, but Android text fields do not. Let's look at how to make platform-specific style changes in NativeScript.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add platform-specific CSS\n+</h4>\n+\n+Add the following as the first line of your app's `app.css` file:\n+\n+``` CSS\n+@import { url('~/platform.css') };\n+```\n+> **IMPORTANT**: NativeScript is consistent with browser implementations, in that `@import` statements must precede all other CSS rules in a file.\n+\n+Next, add a `cssClass=\"link\"` attribute to the sign up button in `login.xml`. The button's markup should look like this:\n+\n+``` XML\n+<Button text=\"Sign up for Groceries\" cssClass=\"link\" />\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+Let's break down what just happened. First, NativeScript supports CSS's `@import` statement for importing one CSS file into another. So this new line of code imports the CSS rules from `platform.css` into `app.css`. But, you might have noticed that Groceries does not have a file named `platform.css`—only `app/platform.android.css` and `app/platform.ios.css` exist. So what's going on here?\n+\n+When you execute `tns run`, or `tns livesync`, the NativeScript CLI takes your code from the `app` folder and places it in the native projects located in the `platforms/ios` and `platforms/android` folders. Here the naming convention comes in: while moving files, the CLI intelligently selects `.android.*` and `.ios.*` files. To give a specific example, in this case the CLI moves `platform.ios.css` into `platforms/ios` and renames it to `platform.css`; similarly, the CLI moves `platform.android.css` into `platforms/android`, and again renames it to `platform.css`. This convention provides a convenient way to branch your code to handle iOS and Android separately, and it's supported for any type of file in NativeScript—not just CSS files. You'll see a few more examples of this convention later in this guide.\n+\n+There's one other change here we need to discuss, and that's the `cssClass` attribute you added to this button:\n+\n+```\n+<Button text=\"Sign up for Groceries\" cssClass=\"link\" />\n+```\n+\n+NativeScript uses the `cssClass` attribute for adding CSS class names to UI components. In this case the class name is used to give the sign up button a slightly different look than the sign in button. You can find the CSS rules associated with this class name in `platform.android.css` and `platform.ios.css`:\n+\n+``` CSS\n+/* From platform.android.css */\n+.link {\n+    background-color: transparent;\n+}\n+\n+/* From platform.ios.css */\n+.link {\n+    border-width: 0;\n+}\n+```\n+\n+> **Tip**: NativeScript also supports selecting elements by the `id` attribute. Refer to the docs for [a full list of the supported selectors](http://docs.nativescript.org/styling#supported-selectors).\n+\n+With these changes in place, you'll notice that the app looks half way decent now, and also has a distinctly different look on iOS and Android:\n+\n+![login 1](img/cli-getting-started/chapter2/ios/3.png)\n+![login 1](img/cli-getting-started/chapter2/android/3.png)\n+\n+Feel free to take some time to play with the look of this app before moving on. You can try adding some additional CSS class names, or adding some page-specific styles in your `login.css` file. When you're ready, let's move on and add an image to this login screen.\n+\n+### Images\n+\n+In NativeScript you use the `<Image>` UI component and its `src` attribute to add images to your pages. The `src` attribute allows you to specify your image in three ways. The first (and simplest) way is to point at the URL of an image:\n+\n+``` XML\n+<Image src=\"https://www.nativescript.org/images/default-source/landingpages/logo.png\" />\n+```\n+\n+The second way is to point at an image that lives within your app's `app` folder. For example if you have an image at `app/images/logo.png`, you can use it with:\n+\n+``` XML\n+<Image src=\"~/images/logo.png\" />\n+```\n+\n+The third way, and the one Groceries uses, is to use platform-specific image resources. Let's add an image to the login screen and then discuss exactly what's happening.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add a logo\n+</h4>\n+\n+In `login.xml`, add the `<Image>` below as the first child of the existing `<StackLayout>` tag:\n+\n+``` XML\n+<Image src=\"res://logo\" stretch=\"none\" horizontalAlignment=\"center\" />\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+The `res://` syntax tells NativeScript to use a platform-specific resource, in this case an image. You might recall from before that platform-specific resources go in your app's `app/App_Resources` folder, and if you look there you'll find a few different image files, several of which are named `logo.png`.\n+\n+Although more complex than putting an image directly in the `app` folder, using platform-specific images gives you more control over image display on different device dimensions. For example iOS lets you use provide three different image files for devices with different pixel densities. As such you'll find logos named `logo.png`, `logo@2x.png`, and `logo@3x.png` in your `App_Resources/iOS` folder. For Android you'll find similar image files in `App_Resources/Android/drawable-hdpi` (for \"high\" dpi, or high dots-per-inch), `App_Resources/Android/drawable-mdpi` (for medium-dpi), and `App_Resources/Android/drawable-ldpi` (for low-dpi).\n+\n+Once these files are in place the NativeScript framework knows how to pick the correct file; all you have to do is reference the image using `res://` and its base file name—i.e. `res://logo`. With this change in place here's what your login screen should look like on iOS and Android:\n+\n+![login 4](img/cli-getting-started/chapter2/ios/4.png)\n+![login 4](img/cli-getting-started/chapter2/android/4.png)\n+\n+At this point your UI looks good, but the app still doesn't actually do anything. Let's look at how you can use JavaScript to add some functionality.\n+\n+## Application logic\n+\n+In this chapter, you'll learn how to add JavaScript logic to your NativeScript app, and you'll be doing so using the base pattern on which the NativeScript framework is built, MVVM, or \"model, view, view model\". Here's what those words mean:\n+\n+- **Model**: The model defines and represents the data. Separating the model from the various views that may use it allows for code reuse.\n+- **View**: The view represents the UI, which in NativeScript is written in XML. The view is often data-bound to the view model so that changes made to the view model in JavaScript instantly trigger visual changes to UI components.\n+- **View Model**: The view model contains the application logic (often including the model), and exposes the data to the view. NativeScript provides a module called 'Observable', which facilitates creating a view model object that can be bound to the view. We'll discuss that shortly.\n+\n+The biggest benefit of separating models, views, and view models, is that you are able to use two-way data binding; that is, changes to data in the model get instantly reflected on the view, and vice versa. The other big benefit is code reuse, as you're often able to reuse models and view models across views.\n+\n+In Groceries, so far you've only touched the view (`login.xml`), and in this chapter you'll be creating a view model. To do so, we first need to introduce one other type of file: the code-behind.\n+\n+### The code-behind\n+\n+In NativeScript a code-behind file is a JavaScript file that shares the same name as the view. For example, the login page's view is named `login.xml`, so its code-behind file is named `login.js`. The code-behind file is where you put all code that interacts with the view itself.\n+\n+Let's look at what you can do in a code-behind file with a simple example.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Construct the login view model\n+</h4>\n+\n+Open `login.xml` and add a `loaded` attribute to the `<Page>` UI component at the top. It should look like this:\n+\n+``` XML\n+<Page loaded=\"load\">\n+```\n+\n+Next, paste the code below in `app/views/login/login.js` to define a `load()` function:\n+\n+``` JavaScript\n+exports.load = function() {\n+    console.log(\"hello\");\n+};\n+```\n+<div class=\"exercise-end\"></div>\n+\n+> **NOTE**: The keyword `exports` is part of [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1), the standard on which both NativeScript and Node.js' implementations of modules are based. In CommonJS-based JavaScript modules, a free variable called `exports` is an object to which a module may add properties and methods to configure its external API. In this case, using `exports` in a code-behind file exposes the function for use in the view, or XML file. That is, the `exports.load` assignment in the code-behind file is what makes `loaded=\"load\"` in the view work.\n+\n+When you run the app with this change, NativeScript triggers the `load()` function you created in the code-behind file, and you should see the word “hello” logged in your terminal.\n+\n+![](img/cli-getting-started/chapter3/terminal-1.png)\n+\n+This simple example shows you how you can append attributes to UI components to run functions in the view's accompanying JavaScript file. Let's use another one of these attributes: `tap`.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Add tap attributes to the login buttons and add their functions\n+</h4>\n+\n+You can add a `tap` attribute that will fire when the user taps or touches a button. In `app/views/login/login.xml`, switch the two buttons at the bottom of the screen to use this markup:\n+\n+``` XML\n+<Button text=\"Sign in\" tap=\"signIn\" />\n+<Button text=\"Sign up for Groceries\" cssClass=\"link\" tap=\"register\" />\n+```\n+\n+Then, at the bottom of the `app/views/login/login.js` file, paste in the following `signIn()` and `register()` functions:\n+\n+``` JavaScript\n+exports.signIn = function() {\n+    alert(\"Signing in\");\n+};\n+\n+exports.register = function() {\n+    alert(\"Registering\");\n+};\n+```\n+<div class=\"exercise-end\"></div>\n+\n+At this point, if you run your app and tap either of the buttons, you will see the appropriate alerts pop up. \n+\n+![login 5](img/cli-getting-started/chapter3/ios/1.png)\n+![login 5](img/cli-getting-started/chapter3/android/1.png)\n+\n+Now that you can see tap gestures working, let's make them do something more interesting than open alerts.\n+\n+### Navigating screens\n+\n+When you tap the “Sign Up for Groceries” button, you would expect a navigational change to a registration screen. This is very easy to do in NativeScript.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Enable the “Sign Up” button on the login screen with a navigational change\n+</h4>\n+\n+In `app/views/login/login.js`, add this line to the top of the file:\n+\n+``` JavaScript\n+var frameModule = require(\"ui/frame\");\n+```\n+\n+Then, replace the current `register()` function with the version shown below:\n+\n+``` JavaScript\n+exports.register = function() {\n+    var topmost = frameModule.topmost();\n+    topmost.navigate(\"./views/register/register\");\n+};\n+```\n+<div class=\"exercise-end\"></div>\n+\n+This function uses the [frame module](http://docs.nativescript.org/ApiReference/ui/frame/README.html), which is the NativeScript module responsible for navigation in your app. Here, you tell the topmost frame, or the frame the user actually sees, to navigate to the register view. \n+\n+If you run your app and click the “Sign up for Groceries” button, you will be sent to the registration screen, which we have pre-built for you.\n+\n+![navigate](img/cli-getting-started/chapter3/ios/2.gif)\n+![navigate](img/cli-getting-started/chapter3/android/2.gif)\n+\n+Now that you can access the registration page, go ahead and sign up for an account to use for the rest of this tutorial.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Register for an account\n+</h4>\n+\n+Open Groceries and click on the “Sign up for Groceries” button to access the registration page. From there, provide an email address and password, and click the “Sign Up” button to create an account.\n+\n+Feel free to use a fake email address and “password” for your password, just remember to write down the credentials you enter as you'll need them later.\n+\n+<div class=\"exercise-end\"></div>\n+\n+> **TIP**: Although our Groceries app doesn't use complex navigation strategies, you have several available to you out of the box, such as the [TabView](http://docs.nativescript.org/ui-views#tabview) and the [SegmentedBar](http://docs.nativescript.org/ui-views#segmentedbar). A SideDrawer component is also available for free via Telerik's [UI for NativeScript](https://www.nativescript.org/blog/welcome-to-telerik-ui-for-nativescript) product.\n+\n+### Accessing UI components\n+\n+Since you have been working with forms in NativeScript, you need to understand how data flows back and forth between the front end and back end. Specifically, you have created a login form, but you need to be able to know what the user types into the fields in order to log them in to your app.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Send data from the front end to the view model\n+</h4>\n+\n+Open `login.xml` and add an `id=\"email_address\"` attribute to the email text field. Its markup should now look like this:\n+\n+``` XML\n+<TextField id=\"email_address\" hint=\"Email Address\" keyboardType=\"email\" />\n+```\n+\n+With an `id` attribute in place, you can now access this text field in your code-behind file. To do that, start by opening `app/views/login/login.js` and adding the code below at the top, underneath the `frameModule` variable.\n+\n+``` JavaScript\n+var viewModule = require(\"ui/core/view\");\n+var email;\n+```\n+\n+> **NOTE**: This line of code imports the [view module](https://docs.nativescript.org/ApiReference/ui/core/view/View.html), which is the base class for all UI components. The module provides a lot of functionality, including the ability to control properties of a view and its children. You're going to use it to get access to the email text field.\n+\n+Next, edit the `load()` function in `login.js` to get a reference to the email address text field:\n+\n+``` JavaScript\n+exports.load = function(args) {\n+    var page = args.object;\n+    email = viewModule.getViewById(page, \"email_address\");\n+};\n+```\n+\n+There are two things to note here. First, because the `load()` function handles the page's `loaded` event, NativeScript passes it a reference to the `<Page>` in the function's argument, which is named `args` by convention. Second, you use the view module's [`getViewById()`](http://docs.nativescript.org/ApiReference/ui/core/view/View.html) function to get a reference to the text field component.\n+\n+Finally, edit the `signIn()` function to log the contents of the text field:\n+\n+``` JavaScript\n+exports.signIn = function() {\n+    console.log(email.text);\n+};\n+```\n+<div class=\"exercise-end\"></div>\n+\n+To see how this works in action, run the app, type some text in the email address text field, and tap the “Sign in” button. If all went well, you should see the text you typed logged in your terminal.\n+\n+![](img/cli-getting-started/chapter3/terminal-2.png)\n+\n+By accessing UI elements in JavaScript, you can control how those elements look and behave on the front end. However, accessing these UI components individually is a very manual process, and it makes it hard to track the state of the UI. This is where view models come in.\n+\n+### Adding a view model\n+\n+NativeScript provides view model functionality in the form of a module called 'Observable'.\n+\n+The Observable is the view model in the MVVM design pattern. It provides a mechanism used for two-way data binding, to enable direct communication between the UI and code-behind file. This means that if the user updates the data in the UI, the change will be automatically reflected in the view model, and vice versa. \n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Create a view model and bind it to the view\n+</h4>\n+\n+To allow for two-way data binding using an Observable, open `login.xml`, and replace the two existing TextField UI components with the two shown below, each including a new `text` attribute:\n+\n+``` XML\n+<TextField id=\"email_address\" text=\"{% raw %}{{ email }}{% endraw %}\" hint=\"Email Address\" keyboardType=\"email\" />\n+<TextField secure=\"true\" text=\"{% raw %}{{ password }}{% endraw %}\" hint=\"Password\" />\n+```\n+\n+> **NOTE**: The use of two curly brackets surrounding the `text` attribute's value delineates a data-bound value. You will be setting corresponding properties with the same name in the view model.\n+\n+Add the following code to the top of `app/views/login/login.js`, which includes the observable module, and defines a new `user` object, which you'll be using as this page's view model:\n+\n+``` JavaScript\n+var observableModule = require(\"data/observable\");\n+\n+var user = new observableModule.Observable({\n+    email: \"user@domain.com\",\n+    password: \"password\"\n+});\n+```\n+\n+Now, replace the existing `load()` function with the one below, which sets `user` as the binding context for the page.\n+\n+``` JavaScript\n+exports.load = function(args) {\n+    var page = args.object;\n+    page.bindingContext = user;\n+};\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+What's going on here?\n+\n+- First, you're creating a `user` view model that is based on the NativeScript Observable module. You create the view model with two properties, `email` and `password`, that are pre-populated with some dummy values.\n+- Next, you bind the page to the `user` view model by setting it as the page's `bindingContext` property. This is specifically what makes the curly bracket syntax work.\n+\n+Simply put, properties placed on a page's binding context are available to XML elements using the `{% raw %}{{ propertyName }}{% endraw %}` syntax. In this case, because JavaScript sets the view model's `email` to `\"user@domain.com\"`, and because you bound the email address text field to that property using `<TextField text=\"{% raw %}{{ email }}{% endraw %}\">`, when you run this app you'll see \"user@domain.com\" appear on the front end.\n+\n+![](img/cli-getting-started/chapter3/ios/3.png)\n+![](img/cli-getting-started/chapter3/android/3.png)\n+\n+What's really cool is that the binding is two-way. Meaning, when the user types text in these text fields, those changes are immediately made to your view model.\n+\n+In order to use these values, and to make this login functional by tying the your app into a backend service, you're going to need the ability to make HTTP calls. And to make HTTP calls in NativeScript you use the NativeScript http module. Let's look at how NativeScript modules work.\n+\n+## NativeScript modules\n+\n+In this chapter you'll learn about NativeScript modules, which are the JavaScript modules in your app's `tns_modules` folder. Whether you've realized it or not, you've already used several NativeScript modules. This includes the modules you've brought in via `require()`—the view module, the frame module, the observable module, and so forth—and also the UI components you've been using in XML, as `<Page>`, `<Image>`, `<TextField>`, and `<Button>` are all just NativeScript modules.\n+\n+If you dig into `tns_modules` you can get an idea of how these modules work. Start by finding the `app/tns_modules/http` folder, which includes the implementation of the http module. It includes:\n+\n+- a `package.json` file that sets the name of the module;\n+- a file containing the module's Android implementation (`http-request.android.js`);\n+- a file containing the module's iOS implementation (`http-request.ios.js`);\n+- a generic file (`http.js`) that abstracts the platform-specific code above into a platform-agnostic API, so that you can make HTTP calls on both platforms using a single JavaScript API.\n+\n+> **NOTE**: You can refer to the [Node.js documentation on folders as modules](https://nodejs.org/api/modules.html#modules_folders_as_modules) for more detailed information on how NativeScript organizes its modules. (Remember that NativeScript modules adhere to the same CommonJS specification that Node.js modules do.)\n+\n+The \\*.ios.\\* and \\*.android.\\* naming convention should look familiar, as it's the exact same convention we used to include Android- and iOS-specific styling in [chapter 2.3](#css). NativeScript uses this same convention to implement its modules on iOS and Android. Now that you know where these modules are, let's take a closer look at what else they can do for your app.\n+\n+### Connecting to a backend with the http module\n+\n+When you created your own account on the registration page, you probably noticed that data was magically going... somewhere. But there's actually no magic involved; the register page invokes a RESTful API provided by [Telerik Backend Services](http://www.telerik.com/backend-services) to register the user for the Groceries service.\n+\n+> **NOTE**: You don't have to use Telerik Backend Services to hit your backend service; you can use any HTTP API in a NativeScript app. Telerik Backend Services is convenient for us to use for this tutorial because it lets us spin up HTTP endpoints quickly.\n+\n+Take a look at `app/shared/config.js`. There's only a small code snippet there, but it includes a hardcoded root path to the Groceries backend that the register page uses, and that you'll be using momentarily:\n+\n+``` JavaScript\n+module.exports = {\n+    apiUrl: \"http://api.everlive.com/v1/GWfRtXi1Lwt4jcqK/\"\n+};\n+```\n+\n+> **TIP**: `config.js` also shows a convenient pattern you can use for sharing configuration variables throughout your app.\n+\n+Next, take a look in the `app/shared/view-models` folder, which contains a few view models that we've pre-packaged into Groceries, and those view models contain the code to hit our backend. You can see this demonstrated in the `user-view-model.js` file's `register()` function.\n+\n+> **NOTE**: In a larger app, it's pretty common to place code that interacts with the backend in separate files, and not directly in the view models. But in our case, the connection code lives directly in the view model for simplicity—which is perfectly reasonable for small apps. \n+\n+Note that the `register()` function uses the config module to get the path to the backend, as well as the [http module](http://docs.nativescript.org/ApiReference/http/README.html) that you examined in the `tns_modules` folder earlier.\n+\n+``` JavaScript\n+var httpModule = require(\"http\");\n+var config = require(\"../../shared/config\");\n+```\n+\n+Let's look at how the http module works by adding another method to the user view model.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Complete the login in the view model\n+</h4>\n+\n+Open `app/shared/view-models/user-view-model.js` and paste the following code directly above the existing `viewModel.register()` function:\n+\n+``` JavaScript\n+viewModel.login = function() {\n+    return new Promise(function(resolve, reject) {\n+        httpModule.request({\n+            url: config.apiUrl + \"oauth/token\",\n+            method: \"POST\",\n+            content: JSON.stringify({\n+                username: viewModel.get(\"email\"),\n+                password: viewModel.get(\"password\"),\n+                grant_type: \"password\"\n+            }),\n+            headers: {\n+                \"Content-Type\": \"application/json\"\n+            }\n+        }).then(function(data) {\n+            config.token = data.content.toJSON().Result.access_token;\n+            resolve();\n+        }).catch(function(error) {\n+            console.log(error);\n+            reject();\n+        });\n+    });\n+};\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+Let's break down what the code you just pasted in does.\n+\n+- You return a new `Promise`, which allows the caller of this function to execute code after the asynchronous login either completes successfully or fails. You'll see how this works when you add code that calls `login()` momentarily.\n+\n+> **TIP**: [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are a part of ECMAScript 6 (the scripting language of which JavaScript is an implementation). Because Promises have been implemented in the two JavaScript engines NativeScript uses—V8 for Android and JavaScriptCore for iOS—Promises are available for use in NativeScript apps.\n+\n+- Next, you use the http module's [`request()` method](http://docs.nativescript.org/ApiReference/http/HttpRequestOptions.html) to POST data to the `apiUrl` from config that we looked at earlier. The username, password and grant_type are sent to this endpoint as a JSON string. (Telerik Backend Services [requires a grant_type parameter](http://docs.telerik.com/platform/backend-services/development/rest-api/users/authenticate-user) for logins.)\n+\n+- Finally, the endpoint's response is handled. `httpModule.request()` returns a `Promise`, which this code uses to resolve or reject its own `Promise`. When the request is successful (the `then()` handler), the code saves a reference to the user's authentication token to be used on subsequent requests.\n+\n+With this code in place let's return to `login.js` to use this new function.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise: Add UserViewModel to the login code-behind</b>\n+</h4>\n+\n+In `login.js`, at the top of the file, add the following reference to `shared/view-models/user-view-model`:\n+\n+``` JavaScript\n+var UserViewModel = require(\"../../shared/view-models/user-view-model\");\n+```\n+\n+Remove the following four lines of code, as you'll be using the `UserViewModel` instead of the `user` you added in the previous chapter.\n+\n+<div class=\"no-copy-button\"></div>\n+\n+``` JavaScript\n+var observableModule = require(\"data/observable\");\n+var user = new observableModule.Observable({\n+    email: \"user@domain.com\",\n+    password: \"password\"\n+});\n+```\n+\n+Next, add the following line of code after the `var UserViewModel = require(...)` line:\n+\n+``` JavaScript\n+var user = new UserViewModel();\n+```\n+\n+Finally, replace the `exports.signIn()` function with the code below:\n+\n+``` JavaScript\n+exports.signIn = function() {\n+    user.login();\n+};\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+Take a moment to look at just how clean your code-behind file is now. The code-behind instantiates a view model (`UserViewModel`), and calls its `signIn()` method when the user taps the view's sign in button. Because the view model is bound to the page's two text fields (remember `{% raw %}{{ email }}{% endraw %}` and `{% raw %}{{ password }}{% endraw %}`), the view model already has the data it needs to perform the actual login.\n+\n+And if you try running your app, and input your account's credentials, you can indeed now login, but... you don't see anything. That's because view models aren't responsible for updating the UI. Instead the view model returns a `Promise` to let the code behind handle the UI. Let's see how you can use that `Promise`, and introduce a new NativeScript module in the process.\n+\n+### Dialog module\n+\n+To utilize the `Promise` that the view model's `login()` function returns, you need to handle two scenarios: what to do when the login works, and what to do when it doesn't.\n+\n+In the case of Groceries, when the login works you're going to navigate the user to the list page, which you'll be building momentarily, and which will let the user add and remove groceries from a list. To do the navigation you'll use the same frame module you used earlier in this guide.\n+\n+The trickier situation is handling when the login fails, and for that you're going to use the dialog module. The dialog module can be used to show [several types](http://docs.nativescript.org/ApiReference/ui/dialogs/HOW-TO.html) of popup UIs in your app, including actionsheets, confirmation boxes, alert boxes, and prompts. It is a highly customizable module, and it allows you to control the buttons you include in your alerts, their text, and the messaging in the alert itself. The dialog module's code is in the `tns_modules/ui` folder with other UI widgets. Let's see how to use this widget on the login page.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Handle an error with a dialog window\n+</h4>\n+\n+Add the following line to the top of `login.js` to import the dialog module:\n+\n+``` JavaScript\n+var dialogsModule = require(\"ui/dialogs\");\n+```\n+\n+Next, re-write your `signIn()` function to look like this:\n+\n+``` JavaScript\n+exports.signIn = function() {\n+    user.login()\n+        .then(function() {\n+            frameModule.topmost().navigate(\"./views/list/list\");\n+        }).catch(function() {\n+            dialogsModule.alert({\n+                message: \"Unfortunately we could not find your account.\",\n+                okButtonText: \"OK\"\n+            });\n+        });\n+};\n+```\n+<div class=\"exercise-end\"></div>\n+\n+This code uses the `Promise` to handle both a successful and unsuccessful login. On success, you call the frame module's `navigate()` method to navigate the user to the (currently empty) list page. On failure, you use the dialog module to show the user an error message. Try inputting some invalid credentials to see what the dialog looks like.\n+\n+![login 8](img/cli-getting-started/chapter4/ios/1.png)\n+![login 8](img/cli-getting-started/chapter4/android/1.png)\n+\n+With that, the login page is now completely functional. Now that you have user management working in your NativeScript app, let's move onto the page that users will use to manage their grocery list. To do that, you need a module that shows items in a list, which is exactly what the ListView module does.\n+\n+> **TIP**: From this point forward in the guide you'll have to log in a lot, so you may find it helpful to hardcode your credentials in the app during development. The easiest way to do that is to pass an email address and password to the `UserViewModel()` constructor, for example:\n+\n+> ``` JavaScript\n+> var user = new UserViewModel({\n+>     email: \"username@domain.com\",\n+>     password: \"password\"\n+> });\n+> ```\n+\n+### ListView\n+\n+As its name implies, the ListView widget lets you show a list of things on the screen, which is exactly what you need for showing a list of groceries. Before tying the grocery list to a backend API, let's start by seeing how to show a hardcoded list of items on the screen.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Construct the list view\n+</h4>\n+\n+Open `app/views/list/list.xml` and paste in the code below, which creates the list where your groceries will reside:\n+\n+``` XML\n+<Page loaded=\"load\">\n+    <GridLayout>\n+        <ListView items=\"{% raw %}{{ groceryList }}{% endraw %}\">\n+            <ListView.itemTemplate>\n+                <Label text=\"{% raw %}{{ name }}{% endraw %}\" horizontalAlignment=\"left\" verticalAlignment=\"center\"/>\n+            </ListView.itemTemplate>\n+        </ListView>\n+    </GridLayout>\n+</Page>\n+```\n+<div class=\"exercise-end\"></div>\n+\n+> **NOTE**: Notice that this page is going to use a `<GridLayout>` to layout the UI components on the screen. As you add more UI components, you'll start dividing the screen into rows and columns, but for now you're just going to let the `<ListView>` take up the full screen (which is the default behavior of a `<GridLayout>` with no attributes).\n+\n+As discussed earlier, even though you're using `<ListView>` in XML, the ListView module is still a NativeScript module. You can find its implementation in the `tns_modules/ui/list-view` folder. If you want to, you could construct a ListView in pure JavaScript code in the code-behind file as shown in [this example](http://docs.nativescript.org/ApiReference/ui/list-view/HOW-TO.html). For most situations using the NativeScript UI modules in XML is easier, so we'll be sticking with XML usage throughout this tutorial.\n+\n+The last thing to note here is the use of `<ListView.itemTemplate>`. This tag gives you the ability to control how each of the ListView's items displays within the list. For now you're using a simple `<Label>` UI component to display the `{% raw %}{{ name }}{% endraw %}` of each grocery.\n+\n+If you run this code as is, you won't see any items in the grocery list. First you need to build out a way to manage data within the ListView module, and to do that you're going to need a new NativeScript module: the ObservableArray.\n+\n+### Working with arrays\n+\n+In the previous section of this guide you saw how to create observables and how to use them to connect XML views with code-behind files and view models. You're going to do the same thing in this section with one additional twist, and it involves making this `items` attribute work:\n+\n+``` XML\n+<ListView items=\"{% raw %}{{ groceryList }}{% endraw %}\">\n+```\n+\n+The ListView module's `items` attribute takes an array, and to create that array on the view model, NativeScript provides a special ObservableArray module. To see how it works, let's start building the list page's code-behind file.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Populate the list view\n+</h4>\n+\n+Open `app/views/list/list.js` and paste in the following code:\n+\n+``` JavaScript\n+var dialogsModule = require(\"ui/dialogs\");\n+var observableModule = require(\"data/observable\");\n+var observableArrayModule = require(\"data/observable-array\");\n+var viewModule = require(\"ui/core/view\");\n+var page;\n+\n+var pageData = new observableModule.Observable({\n+    groceryList: new observableArrayModule.ObservableArray([\n+        { name: \"eggs\" },\n+        { name: \"bread\" },\n+        { name: \"cereal\" }\n+    ])\n+});\n+\n+exports.load = function(args) {\n+    page = args.object;\n+    page.bindingContext = pageData;\n+};\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+Here, you're creating a new Observable object called `pageData`, which you set as the page's `bindingContext` in the `load()` function. Inside the Observable, you set a single `\"groceryList\"` property to be a new instance of the ObservableArray module. Notice how the `\"groceryList\"` property corresponds to `<ListView items=\"{% raw %}{{ groceryList }}{% endraw %}\">`, and each array entry's `\"name\"` property corresponds to `<Label text=\"{% raw %}{{ name }}{% endraw %}\">`. If you run your app you'll see the list screen now shows the hardcoded data:\n+\n+![list 1](img/cli-getting-started/chapter4/ios/2.png)\n+![list 1](img/cli-getting-started/chapter4/android/2.png)\n+\n+Now that we have items on the screen let's look at how you can tie this list to a backend instead of hardcoded data. To do so you'll switch the list page to use a view model, much like you did with the login page.\n+\n+A starting view model for this page is already in the file at `app/shared/view-models/grocery-list-view-model.js`, which you can see contains the code that looks a lot like you already have in `list.js`:\n+\n+``` JavaScript\n+var config = require(\"../../shared/config\");\n+var httpModule = require(\"http\");\n+var observableArrayModule = require(\"data/observable-array\");\n+\n+function GroceryListViewModel(items) {\n+    var viewModel = new observableArrayModule.ObservableArray(items);\n+    return viewModel;\n+}\n+\n+module.exports = GroceryListViewModel;\n+```\n+\n+Let's expand on this to tie this view model to a backend.\n+\n+<h4 class=\"exercise-start\">\n+    <b>Exercise</b>: Populate a list view from a backend\n+</h4>\n+\n+You're going to start by changing `list.js` to use the `GroceryListViewModel`. First, `require()` the `GroceryListViewModel` so you can use it:\n+\n+``` JavaScript\n+var GroceryListViewModel = require(\"../../shared/view-models/grocery-list-view-model\");\n+```\n+\n+Next, remove the existing `var pageData` assignment:\n+\n+<div class=\"no-copy-button\"></div>\n+\n+``` JavaScript\n+// Remove these seven lines of code\n+var pageData = new observableModule.Observable({\n+    groceryList: new observableArrayModule.ObservableArray([\n+        { name: \"eggs\" },\n+        { name: \"bread\" },\n+        { name: \"cereal\" }\n+    ])\n+});\n+```\n+\n+And add the code below in the same location:\n+\n+``` JavaScript\n+var groceryList = new GroceryListViewModel([]);\n+var pageData = new observableModule.Observable({\n+    groceryList: groceryList\n+});\n+```\n+\n+Finally, replace the existing `exports.load()` function with the one below, which calls two new methods on the view model—`empty()` and `load()`.\n+\n+``` JavaScript\n+exports.load = function(args) {\n+    page = args.object;\n+    page.bindingContext = pageData;\n+\n+    groceryList.empty();\n+    groceryList.load();\n+};\n+```\n+\n+In this code, `groceryList` is now referencing the grocery list model, and the `load()` function now empties the list, and then calls the view model's `load()` function to reload the data from the backend.\n+\n+The last piece to make this work is actually implementing the `empty()` and `load()` functions in the view model. Open `app/shared/view-models/grocery-list-view-model.js`, and paste the following code between the `var viewModel` assignment, and the `return viewModel` statement.\n+\n+``` JavaScript\n+viewModel.load = function() {\n+    httpModule.getJSON({\n+        url: config.apiUrl + \"Groceries\",\n+        method: \"GET\",\n+        headers: {\n+            \"Authorization\": \"Bearer \" + config.token\n+        }\n+    }).then(function(data) {\n+        data.Result.forEach(function(grocery) {\n+            viewModel.push({\n+                name: grocery.Name,\n+                id: grocery.Id\n+            });\n+        });\n+    });\n+};\n+\n+viewModel.empty = function() {\n+    while (viewModel.length) {\n+        viewModel.pop();\n+    }\n+};\n+```\n+\n+<div class=\"exercise-end\"></div>\n+\n+The code to do an HTTP call should look familiar, as it's using the same http module you used in the previous section. Here, you're using the http module's `getJSON()` method, which automatically takes care of formatting the backend's response as JSON.\n+\n+If you load the app and login with email address \"tj.vantoll@gmail.com\" and password \"password\", you should see a list of groceries that looks something like this:","path":"getting-started.md","position":1123,"original_position":1123,"commit_id":"9965bf32a4d47c9b8e0ff26414fe7aeb2e575836","original_commit_id":"9965bf32a4d47c9b8e0ff26414fe7aeb2e575836","user":{"login":"ikoevska","id":3539221,"avatar_url":"https://avatars.githubusercontent.com/u/3539221?v=3","gravatar_id":"","url":"https://api.github.com/users/ikoevska","html_url":"https://github.com/ikoevska","followers_url":"https://api.github.com/users/ikoevska/followers","following_url":"https://api.github.com/users/ikoevska/following{/other_user}","gists_url":"https://api.github.com/users/ikoevska/gists{/gist_id}","starred_url":"https://api.github.com/users/ikoevska/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ikoevska/subscriptions","organizations_url":"https://api.github.com/users/ikoevska/orgs","repos_url":"https://api.github.com/users/ikoevska/repos","events_url":"https://api.github.com/users/ikoevska/events{/privacy}","received_events_url":"https://api.github.com/users/ikoevska/received_events","type":"User","site_admin":false},"body":"log in","created_at":"2015-08-31T11:02:36Z","updated_at":"2015-08-31T11:02:36Z","html_url":"https://github.com/NativeScript/docs/pull/128#discussion_r38301999","pull_request_url":"https://api.github.com/repos/NativeScript/docs/pulls/128","_links":{"self":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/comments/38301999"},"html":{"href":"https://github.com/NativeScript/docs/pull/128#discussion_r38301999"},"pull_request":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/128"}}},"pull_request":{"url":"https://api.github.com/repos/NativeScript/docs/pulls/128","id":42842321,"html_url":"https://github.com/NativeScript/docs/pull/128","diff_url":"https://github.com/NativeScript/docs/pull/128.diff","patch_url":"https://github.com/NativeScript/docs/pull/128.patch","issue_url":"https://api.github.com/repos/NativeScript/docs/issues/128","number":128,"state":"open","locked":false,"title":"New quick start","user":{"login":"tjvantoll","id":544280,"avatar_url":"https://avatars.githubusercontent.com/u/544280?v=3","gravatar_id":"","url":"https://api.github.com/users/tjvantoll","html_url":"https://github.com/tjvantoll","followers_url":"https://api.github.com/users/tjvantoll/followers","following_url":"https://api.github.com/users/tjvantoll/following{/other_user}","gists_url":"https://api.github.com/users/tjvantoll/gists{/gist_id}","starred_url":"https://api.github.com/users/tjvantoll/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjvantoll/subscriptions","organizations_url":"https://api.github.com/users/tjvantoll/orgs","repos_url":"https://api.github.com/users/tjvantoll/repos","events_url":"https://api.github.com/users/tjvantoll/events{/privacy}","received_events_url":"https://api.github.com/users/tjvantoll/received_events","type":"User","site_admin":false},"body":"Ping @atanasovg @hdeshev \r\n\r\nI was able to get the Jekyll setup working which helped a lot for testing this. Here's the side nav I was talking about:\r\n\r\n![screen shot 2015-08-19 at 1 09 19 pm](https://cloud.githubusercontent.com/assets/544280/9363812/8d463210-4676-11e5-8a8b-df5573521087.png)\r\n\r\nThe two problems are that, 1) this requires a bit of CSS and JavaScript to get working (see the top and bottom of [this file](https://raw.githubusercontent.com/tjvantoll/docs/83e2ac5899c4035f4c8c89e4f8eb5a8fe08eadad/getting-started.md)), and 2) the nav isn't fixed like it is on <http://nativescript.github.io/quick-start/>. I can make it work, but it gets really hacky as I basically have to reimplement the site's layout for this page.\r\n\r\nThe being said, other than those two things I was pleasantly surprised by how easy it was to port this content and get everything working. Let me know what you think.","created_at":"2015-08-19T17:38:09Z","updated_at":"2015-08-31T11:02:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"73251ab89b463fffc191b56985e2b9d033919859","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/NativeScript/docs/pulls/128/commits","review_comments_url":"https://api.github.com/repos/NativeScript/docs/pulls/128/comments","review_comment_url":"https://api.github.com/repos/NativeScript/docs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NativeScript/docs/issues/128/comments","statuses_url":"https://api.github.com/repos/NativeScript/docs/statuses/9965bf32a4d47c9b8e0ff26414fe7aeb2e575836","head":{"label":"tjvantoll:new-quick-start","ref":"new-quick-start","sha":"9965bf32a4d47c9b8e0ff26414fe7aeb2e575836","user":{"login":"tjvantoll","id":544280,"avatar_url":"https://avatars.githubusercontent.com/u/544280?v=3","gravatar_id":"","url":"https://api.github.com/users/tjvantoll","html_url":"https://github.com/tjvantoll","followers_url":"https://api.github.com/users/tjvantoll/followers","following_url":"https://api.github.com/users/tjvantoll/following{/other_user}","gists_url":"https://api.github.com/users/tjvantoll/gists{/gist_id}","starred_url":"https://api.github.com/users/tjvantoll/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjvantoll/subscriptions","organizations_url":"https://api.github.com/users/tjvantoll/orgs","repos_url":"https://api.github.com/users/tjvantoll/repos","events_url":"https://api.github.com/users/tjvantoll/events{/privacy}","received_events_url":"https://api.github.com/users/tjvantoll/received_events","type":"User","site_admin":false},"repo":{"id":20927953,"name":"docs","full_name":"tjvantoll/docs","owner":{"login":"tjvantoll","id":544280,"avatar_url":"https://avatars.githubusercontent.com/u/544280?v=3","gravatar_id":"","url":"https://api.github.com/users/tjvantoll","html_url":"https://github.com/tjvantoll","followers_url":"https://api.github.com/users/tjvantoll/followers","following_url":"https://api.github.com/users/tjvantoll/following{/other_user}","gists_url":"https://api.github.com/users/tjvantoll/gists{/gist_id}","starred_url":"https://api.github.com/users/tjvantoll/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjvantoll/subscriptions","organizations_url":"https://api.github.com/users/tjvantoll/orgs","repos_url":"https://api.github.com/users/tjvantoll/repos","events_url":"https://api.github.com/users/tjvantoll/events{/privacy}","received_events_url":"https://api.github.com/users/tjvantoll/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tjvantoll/docs","description":"Docs, API Reference and Code Snippets for NativeScript","fork":true,"url":"https://api.github.com/repos/tjvantoll/docs","forks_url":"https://api.github.com/repos/tjvantoll/docs/forks","keys_url":"https://api.github.com/repos/tjvantoll/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tjvantoll/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tjvantoll/docs/teams","hooks_url":"https://api.github.com/repos/tjvantoll/docs/hooks","issue_events_url":"https://api.github.com/repos/tjvantoll/docs/issues/events{/number}","events_url":"https://api.github.com/repos/tjvantoll/docs/events","assignees_url":"https://api.github.com/repos/tjvantoll/docs/assignees{/user}","branches_url":"https://api.github.com/repos/tjvantoll/docs/branches{/branch}","tags_url":"https://api.github.com/repos/tjvantoll/docs/tags","blobs_url":"https://api.github.com/repos/tjvantoll/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tjvantoll/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tjvantoll/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/tjvantoll/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tjvantoll/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/tjvantoll/docs/languages","stargazers_url":"https://api.github.com/repos/tjvantoll/docs/stargazers","contributors_url":"https://api.github.com/repos/tjvantoll/docs/contributors","subscribers_url":"https://api.github.com/repos/tjvantoll/docs/subscribers","subscription_url":"https://api.github.com/repos/tjvantoll/docs/subscription","commits_url":"https://api.github.com/repos/tjvantoll/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/tjvantoll/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/tjvantoll/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/tjvantoll/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/tjvantoll/docs/contents/{+path}","compare_url":"https://api.github.com/repos/tjvantoll/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tjvantoll/docs/merges","archive_url":"https://api.github.com/repos/tjvantoll/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tjvantoll/docs/downloads","issues_url":"https://api.github.com/repos/tjvantoll/docs/issues{/number}","pulls_url":"https://api.github.com/repos/tjvantoll/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/tjvantoll/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/tjvantoll/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tjvantoll/docs/labels{/name}","releases_url":"https://api.github.com/repos/tjvantoll/docs/releases{/id}","created_at":"2014-06-17T15:01:41Z","updated_at":"2015-02-11T21:12:43Z","pushed_at":"2015-08-28T21:16:02Z","git_url":"git://github.com/tjvantoll/docs.git","ssh_url":"git@github.com:tjvantoll/docs.git","clone_url":"https://github.com/tjvantoll/docs.git","svn_url":"https://github.com/tjvantoll/docs","homepage":null,"size":6197,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"NativeScript:master","ref":"master","sha":"3e34134837f29006bad86c916719c25a2aa9bba2","user":{"login":"NativeScript","id":7392261,"avatar_url":"https://avatars.githubusercontent.com/u/7392261?v=3","gravatar_id":"","url":"https://api.github.com/users/NativeScript","html_url":"https://github.com/NativeScript","followers_url":"https://api.github.com/users/NativeScript/followers","following_url":"https://api.github.com/users/NativeScript/following{/other_user}","gists_url":"https://api.github.com/users/NativeScript/gists{/gist_id}","starred_url":"https://api.github.com/users/NativeScript/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NativeScript/subscriptions","organizations_url":"https://api.github.com/users/NativeScript/orgs","repos_url":"https://api.github.com/users/NativeScript/repos","events_url":"https://api.github.com/users/NativeScript/events{/privacy}","received_events_url":"https://api.github.com/users/NativeScript/received_events","type":"Organization","site_admin":false},"repo":{"id":20398807,"name":"docs","full_name":"NativeScript/docs","owner":{"login":"NativeScript","id":7392261,"avatar_url":"https://avatars.githubusercontent.com/u/7392261?v=3","gravatar_id":"","url":"https://api.github.com/users/NativeScript","html_url":"https://github.com/NativeScript","followers_url":"https://api.github.com/users/NativeScript/followers","following_url":"https://api.github.com/users/NativeScript/following{/other_user}","gists_url":"https://api.github.com/users/NativeScript/gists{/gist_id}","starred_url":"https://api.github.com/users/NativeScript/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NativeScript/subscriptions","organizations_url":"https://api.github.com/users/NativeScript/orgs","repos_url":"https://api.github.com/users/NativeScript/repos","events_url":"https://api.github.com/users/NativeScript/events{/privacy}","received_events_url":"https://api.github.com/users/NativeScript/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NativeScript/docs","description":"Docs, API Reference and Code Snippets for NativeScript","fork":false,"url":"https://api.github.com/repos/NativeScript/docs","forks_url":"https://api.github.com/repos/NativeScript/docs/forks","keys_url":"https://api.github.com/repos/NativeScript/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NativeScript/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NativeScript/docs/teams","hooks_url":"https://api.github.com/repos/NativeScript/docs/hooks","issue_events_url":"https://api.github.com/repos/NativeScript/docs/issues/events{/number}","events_url":"https://api.github.com/repos/NativeScript/docs/events","assignees_url":"https://api.github.com/repos/NativeScript/docs/assignees{/user}","branches_url":"https://api.github.com/repos/NativeScript/docs/branches{/branch}","tags_url":"https://api.github.com/repos/NativeScript/docs/tags","blobs_url":"https://api.github.com/repos/NativeScript/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NativeScript/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NativeScript/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/NativeScript/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NativeScript/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/NativeScript/docs/languages","stargazers_url":"https://api.github.com/repos/NativeScript/docs/stargazers","contributors_url":"https://api.github.com/repos/NativeScript/docs/contributors","subscribers_url":"https://api.github.com/repos/NativeScript/docs/subscribers","subscription_url":"https://api.github.com/repos/NativeScript/docs/subscription","commits_url":"https://api.github.com/repos/NativeScript/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/NativeScript/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/NativeScript/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/NativeScript/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/NativeScript/docs/contents/{+path}","compare_url":"https://api.github.com/repos/NativeScript/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NativeScript/docs/merges","archive_url":"https://api.github.com/repos/NativeScript/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NativeScript/docs/downloads","issues_url":"https://api.github.com/repos/NativeScript/docs/issues{/number}","pulls_url":"https://api.github.com/repos/NativeScript/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/NativeScript/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/NativeScript/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NativeScript/docs/labels{/name}","releases_url":"https://api.github.com/repos/NativeScript/docs/releases{/id}","created_at":"2014-06-02T09:28:14Z","updated_at":"2015-08-17T18:48:49Z","pushed_at":"2015-08-28T21:16:03Z","git_url":"git://github.com/NativeScript/docs.git","ssh_url":"git@github.com:NativeScript/docs.git","clone_url":"https://github.com/NativeScript/docs.git","svn_url":"https://github.com/NativeScript/docs","homepage":null,"size":7735,"stargazers_count":219,"watchers_count":219,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":47,"mirror_url":null,"open_issues_count":20,"forks":47,"open_issues":20,"watchers":219,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/128"},"html":{"href":"https://github.com/NativeScript/docs/pull/128"},"issue":{"href":"https://api.github.com/repos/NativeScript/docs/issues/128"},"comments":{"href":"https://api.github.com/repos/NativeScript/docs/issues/128/comments"},"review_comments":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/128/comments"},"review_comment":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NativeScript/docs/pulls/128/commits"},"statuses":{"href":"https://api.github.com/repos/NativeScript/docs/statuses/9965bf32a4d47c9b8e0ff26414fe7aeb2e575836"}}}}