đź“ş "One project. One language. Three apps." Learn more in our upcoming code sharing webinar!

NativeScript Core

Application Architecture

In this article we are going to go through the core concepts of the Angular framework, with an an emphasis on the specifics of using Angular with NativeScript.

Note: The best place to learn about Angular concepts is on angular.io. We are going to refer to it in many sections in this article.

Components

Components are the main building block of Angular applications. They define the application UI and the logic that controls it. Let's take look at the following component:

import {Component} from "@angular/core";

@Component({
    selector: "my-app",
    template: `
        <StackLayout orientation="vertical">
            <Label [text]="message" (tap)="onTap()"></Label>
        </StackLayout>`
})
export class AppComponent {
    public message: string = "Hello, Angular!";
    public onTap() {
        this.message = "OHAI";
    }
}

Each component has two parts - the component class and the component template:

  • The component class (class AppComponent in the example) defines the application logic of the component - its behavior.
  • The component template defines the UI of the component - also called a view. It is the topic of the next section.

The class and the view communicate with each other using data binding and events.

You can learn more about components on angular.io.

There are almost no differences between creating component classes in Angular web apps and NativeScript apps.

Template Syntax

The template defines the view of the component - what is actually rendered. In NativeScript applications the template is defined with XML using NativeScript UI elements. It is different from HTML. So instead of <input>, <span>, <div> etc. - we have <text-field>, <label> and layouts.

The important thing is that although the elements are different - all of the Angular’s template syntax works exactly the same. So you can still use template expressions, bindings, templates as well as all the built-in directives.

When defining the template you can use both CamelCase and kebab-case. So, both <StackLayout> and <stack-layout> are valid inside a template definition.

There is no text-node element in NativeScript so the following template will render an empty StackLayout:

<StackLayout orientation="vertical">
     {{ message }}  
</StackLayout>

To fix it, you can just use a Label to show the message:

<StackLayout orientation="vertical">
    <Label text="{{ message }}"></Label> 
</StackLayout>

Data Binding

Data binding is a mechanism for connecting the parts of the view (template) with parts of the component class. There are several forms of data binding in an Angular app.

<StackLayout orientation="vertical">
    <Label [text]="message"></Label>
    <Button text="tap me" (tap)="onTap()"></Button>
    <TextField [(ngModel)]="message"></TextField>
</StackLayout>

Let's examine:

  • [text]="message" - binds the text property of the Label to the message property of the component. Whenever the message is updated the label will be updated as well. This kind of binding is called “one-way binding” - the data flows in one direction from the component to the view.
  • (tap)="onTap()" - means that when the button is tapped the onTap method in the component should be called. This kind of binding is called “event binding” - here the data flows from the view to the component.
  • [(ngModel)]="message" - This is an example of “two-way binding”. When the user types something in the TextField - the message property of the component will be changed and vice versa - if your code changes the message property - the UI will be updated. Data flows in both directions, thus the name.

This topic is covered in depth in the data binding article.

Directives

Directives allow you to create and attach behavior to the visual tree. There are three kinds of directives:

  • Components - We already talked about them. Components are actually directives which have their own template.
  • Structural Directives - alter the visual tree by adding, removing or replacing elements. The most commonly used structural directives are *ngIf and *ngFor.
  • Attribute Directive - change the appearance or behavior of UI elements. One of the most commonly used attribute directives is ngClass.

When it comes to NativeScript specifics - there are again almost no differences as far as directives are concerned. You are free to use all the built-in Angular directives; you’re also free to write your own.

Dependency Injection

Angular ships with its own dependency injection (DI for short) framework. It is extremely powerful and fully usable in NativeScript. You can read more about it on angular.io.

The navigation inside a NativeScript application is done with the Angular Router. However, you can choose between two router-outlets:

  • router-outlet - the built in Angular router outlet. It replaces the content of the outlet with the templates of different component.
  • page-router-outlet - uses NativeScript page navigation.

To use the Router you will have to import NativeScriptRouterModule into AppModule:

import { NativeScriptRouterModule } from "nativescript-angular/router";

@NgModule({
    bootstrap: [GroceriesApp],
    imports: [
        NativeScriptRouterModule,
        NativeScriptRouterModule.forRoot(routes)
    ]
})
export class GroceriesAppModule { }

Navigation is covered in detail in the navigation article.