Application Architecture
In this article we are going to go through the core concepts of the Angular framework, with 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 thetext
property of theLabel
to themessage
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 theonTap
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 theTextField
- themessage
property of the component will be changed and vice versa - if your code changes themessage
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.
Navigation
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.