Ionic 4, Angular 7 and Cordova Tutorial: Build CRUD Mobile Apps

by Didin J. on Nov 09, 2018 Ionic 4, Angular 7 and Cordova Tutorial: Build CRUD Mobile Apps

A comprehensive step by step tutorial on building CRUD (Create, Read, Update, Delete) Hybrid Mobile Apps using Ionic 4, Angular 7 and Cordova

A comprehensive step by step tutorial on building CRUD (Create, Read, Update, Delete) Hybrid Mobile Apps using Ionic 4, Angular 7 and Cordova. The Angular 7 just released a few weeks ago and Ionic 4 still in beta version. So, we are an experiment using both frameworks as a hybrid Mobile Apps. For the backend, we are using our existing Node, Express.js, and MongoDB RESTful API. There are little new features in Angular 7, but we just take a bit for this tutorial.


Table of Contents:


The following tools, frameworks, and modules are required for this tutorial:

Before going to the main steps, we assume that you have to install Node.js. Next, upgrade or install new Ionic 4 CLI by open the terminal or Node command line then type this command.

sudo npm install -g ionic

You will get the latest Ionic CLI in your terminal or command line. Check the version by type this command.

ionic --version
4.3.1


1. Ionic 4, Angular 7 and Cordova Tutorial: Create a New Application

To create a new Ionic 4 and Angular 7 application, type this command in your terminal.

ionic start ionic4-angular7-crud tabs --type=angular

If you see this question, just type `N` for because we will installing or adding Cordova later.

Integrate your new app with Cordova to target native iOS and Android? (y/N) N

After installing `NPM` modules and dependencies, you will see this question, just type `N` because we are not using it yet.

Install the free Ionic Pro SDK and connect your app? (Y/n) N

Next, go to the newly created app folder.

cd ./ionic4-angular7-crud

You will see the Angular version still using 6 in the `package.json`.

"dependencies": {
  "@angular/common": "~6.1.1",
  "@angular/core": "~6.1.1",
  "@angular/forms": "~6.1.1",
  "@angular/http": "~6.1.1",
  "@angular/platform-browser": "~6.1.1",
  "@angular/platform-browser-dynamic": "~6.1.1",
  "@angular/router": "~6.1.1",
  "@ionic-native/core": "5.0.0-beta.21",
  "@ionic-native/splash-screen": "5.0.0-beta.21",
  "@ionic-native/status-bar": "5.0.0-beta.21",
  "@ionic/angular": "4.0.0-beta.15",
  "core-js": "^2.5.3",
  "rxjs": "6.2.2",
  "zone.js": "^0.8.26"
},

Next, we have to upgrade the angular version to 7. You can replace all dependencies in `package.json` with this.

"dependencies": {
  "@angular/common": "^7.0.3",
  "@angular/core": "^7.0.3",
  "@angular/forms": "^7.0.3",
  "@angular/http": "^7.0.3",
  "@angular/platform-browser": "^7.0.3",
  "@angular/platform-browser-dynamic": "^7.0.3",
  "@angular/router": "^7.0.3",
  "@ionic-native/core": "5.0.0-beta.21",
  "@ionic-native/splash-screen": "5.0.0-beta.21",
  "@ionic-native/status-bar": "5.0.0-beta.21",
  "@ionic/angular": "4.0.0-beta.15",
  "core-js": "^2.5.3",
  "rxjs": "6.2.2",
  "zone.js": "^0.8.26"
},
"devDependencies": {
  "@angular-devkit/architect": "^0.10.4",
  "@angular-devkit/build-angular": "^0.10.4",
  "@angular-devkit/core": "^7.0.4",
  "@angular-devkit/schematics": "^7.0.4",
  "@angular/cli": "^7.0.4",
  "@angular/compiler": "^7.0.3",
  "@angular/compiler-cli": "^7.0.3",
  "@angular/language-service": "^7.0.3",
  "@ionic/angular-toolkit": "^1.0.0",
  "@ionic/lab": "^1.0.13",
  "@types/jasmine": "^2.8.11",
  "@types/jasminewd2": "^2.0.6",
  "@types/node": "^10.12.3",
  "codelyzer": "~4.5.0",
  "jasmine-core": "~2.99.1",
  "jasmine-spec-reporter": "~4.2.1",
  "karma": "~3.0.0",
  "karma-chrome-launcher": "~2.2.0",
  "karma-coverage-istanbul-reporter": "~2.0.0",
  "karma-jasmine": "~1.1.1",
  "karma-jasmine-html-reporter": "^0.2.2",
  "protractor": "~5.4.0",
  "ts-node": "~7.0.0",
  "tslint": "~5.11.0",
  "typescript": "^3.1.6"
},

Then run this commands.

rm -rf node_modules
npm install

As usual, run the Ionic 4 and Angular 7 app for the first time, but before run as `lab` mode, type this command to install `@ionic/lab`.

npm install --save-dev @ionic/lab
ionic serve -l

Now, open the browser and you will the Ionic 4 and Angular 7 app with the iOS, Android, or Windows view. If you see a normal Ionic 4 tabs application, that's mean the Angular upgrade process is successful.

Ionic 4, Angular 7 and Cordova Tutorial: Build CRUD Mobile Apps - Ionic 4 Labs


2. Ionic 4, Angular 7 and Cordova Tutorial: Install Material and CDK

To install Angular 7 Material and CDK, simply run this command.

ng add @angular/material

Type enter or yes for every question that showed up.

? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink
   [ Preview: https://material.angular.io?theme=indigo-pink ]
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes

Next, register all required Angular Material components or modules to `app.module.ts`. Open and edit that file then add this imports.

import {
  MatInputModule,
  MatPaginatorModule,
  MatProgressSpinnerModule,
  MatSortModule,
  MatTableModule,
  MatIconModule,
  MatButtonModule,
  MatCardModule,
  MatFormFieldModule } from "@angular/material";
import { DragDropModule } from '@angular/cdk/drag-drop';
import { ScrollingModule } from '@angular/cdk/scrolling';

Register the above modules to `@NgModule` imports.

imports: [
  BrowserModule,
  IonicModule.forRoot(),
  AppRoutingModule,
  BrowserAnimationsModule,
  DragDropModule,
  ScrollingModule,
  MatInputModule,
  MatPaginatorModule,
  MatProgressSpinnerModule,
  MatSortModule,
  MatTableModule,
  MatIconModule,
  MatButtonModule,
  MatCardModule,
  MatFormFieldModule
],


3. Ionic 4, Angular 7 and Cordova Tutorial: Create RESTful API Service

Before creating a service for RESTful API access, first, we have to install or register `HttpClientModule`. Open and edit `src/app/app.module.ts` then add this import.

import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

Add it to `@NgModule` imports after `BrowserModule`.

imports: [
  BrowserModule,
  FormsModule,
  HttpClientModule,
  AppRoutingModule
],

We will use type specifier to get a typed result object. For that, create a new Typescript file `src/app/product.ts` then add this lines of Typescript codes.

export class Product {
  id: number;
  prod_name: string;
  prod_desc: string;
  prod_price: number;
  updated_at: Date;
}

Next, generate an Angular 7 service by typing this command.

ng g service api

Next, open and edit `src/app/api.service.ts` then add this imports.

import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Product } from './product';

Add these constants before the `@Injectable`.

const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const apiUrl = "/api/v1/products";

Inject `HttpClient` module to the constructor.

constructor(private http: HttpClient) { }

Add the error handler function.

private handleError<T> (operation = 'operation', result?: T) {
  return (error: any): Observable<T> => {

    // TODO: send the error to remote logging infrastructure
    console.error(error); // log to console instead

    // Let the app keep running by returning an empty result.
    return of(result as T);
  };
}

Add all CRUD (create, read, update, delete) functions of products data.

getProduct(id): Observable<Product> {
  const url = `${apiUrl}/${id}`;
  return this.http.get<Product>(url).pipe(
    tap(_ => console.log(`fetched product id=${id}`)),
    catchError(this.handleError<Product>(`getProduct id=${id}`))
  );
}

addProduct (product): Observable<Product> {
  return this.http.post<Product>(apiUrl, product, httpOptions).pipe(
    tap((product: Product) => console.log(`added product w/ id=${product._id}`)),
    catchError(this.handleError<Product>('addProduct'))
  );
}

updateProduct (id, product): Observable<any> {
  const url = `${apiUrl}/${id}`;
  return this.http.put(url, product, httpOptions).pipe(
    tap(_ => console.log(`updated product id=${id}`)),
    catchError(this.handleError<any>('updateProduct'))
  );
}

deleteProduct (id): Observable<Product> {
  const url = `${apiUrl}/${id}`;

  return this.http.delete<Product>(url, httpOptions).pipe(
    tap(_ => console.log(`deleted product id=${id}`)),
    catchError(this.handleError<Product>('deleteProduct'))
  );
}


4. Ionic 4, Angular 7 and Cordova Tutorial: Modify Tabs Page

We will put every CRUD pages inside tabs that previously created as default Ionic 4 starter template. We will display a list of data inside home page, so for edit, add and details we will modify the existing page or tab items. Rename contact page folder, files and it's filed contents as `add`. Rename about page folder, files and it's filed contents as `edit`. Type this command to generate a new details page.

ionic g page details

Next, open and edit `src/app/tabs/tabs.router.module.ts` then replace and add this imports.

import { HomePage } from '../home/home.page';
import { AddPage } from '../add/add.page';
import { EditPage } from '../edit/edit.page';
import { DetailsPage } from '../details/details.page';

Change the route constant as below.

const routes: Routes = [
  {
    path: 'tabs',
    component: TabsPage,
    children: [
      {
        path: '',
        redirectTo: '/tabs/(home:home)',
        pathMatch: 'full',
      },
      {
        path: 'home',
        outlet: 'home',
        component: HomePage
      },
      {
        path: 'add',
        outlet: 'add',
        component: AddPage
      },
      {
        path: ':id',
        outlet: 'edit',
        component: EditPage
      },
      {
        path: ':id',
        outlet: 'details',
        component: DetailsPage
      }
    ]
  },
  {
    path: '',
    redirectTo: '/tabs/(home:home)',
    pathMatch: 'full'
  }
];

Next, open and edit `src/app/tabs/tabs.module.ts` then add or replace this imports.

import { AddPageModule } from '../add/add.module';
import { EditPageModule } from '../edit/edit.module';
import { HomePageModule } from '../home/home.module';
import { DetailsPageModule } from '../details/details.module';

Add those imported modules to the `@NgModule` imports array.

imports: [
  IonicModule,
  CommonModule,
  FormsModule,
  TabsPageRoutingModule,
  HomePageModule,
  AddPageModule,
  EditPageModule,
  DetailsPageModule
],

Next, open and edit `src/app/tabs/tabs.page.html` then replace all HTML tags with this.

<ion-tabs>

  <ion-tab tab="home">
    <ion-router-outlet name="home"></ion-router-outlet>
  </ion-tab>
  <ion-tab tab="details">
    <ion-router-outlet name="details"></ion-router-outlet>
  </ion-tab>
  <ion-tab tab="add">
    <ion-router-outlet name="add"></ion-router-outlet>
  </ion-tab>
  <ion-tab tab="edit">
    <ion-router-outlet name="edit"></ion-router-outlet>
  </ion-tab>

  <ion-tab-bar slot="bottom">

    <ion-tab-button tab="home" href="/tabs/(home:home)">
      <ion-icon name="home"></ion-icon>
      <ion-label>Home</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="details" href="/tabs/(details:null)">
      <ion-icon name="eye"></ion-icon>
      <ion-label>Details</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="add" href="/tabs/(add:add)">
      <ion-icon name="add"></ion-icon>
      <ion-label>Add</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="edit" href="/tabs/(edit:null)">
      <ion-icon name="create"></ion-icon>
      <ion-label>Edit</ion-label>
    </ion-tab-button>

  </ion-tab-bar>

</ion-tabs>


5. Ionic 4, Angular 7 and Cordova Tutorial: View List of Data

To display list of data, open and edit `src/app/home/home.page.ts` then add/replace this imports.

import { Component, OnInit } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { ActivatedRoute, Router } from '@angular/router';
import { ApiService } from '../api.service';
import { Product } from '../product';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';

Next, add the constructor then inject those modules to the constructor.

constructor(public api: ApiService,
  public loadingController: LoadingController,
  public router: Router,
  public route: ActivatedRoute) { }

Remove all default generated variable, function and constructor body if exists then add this variable before the constructor for hold classroom data that get from the service.

products: Product[] = [];

Add function for getting Product list from API.

async getProducts() {
  const loading = await this.loadingController.create({
    message: 'Loading...'
  });
  await loading.present();
  await this.api.getProducts()
    .subscribe(res => {
      this.products = res;
      console.log(this.products);
      loading.dismiss();
    }, err => {
      console.log(err);
      loading.dismiss();
    });
}

Add Angular 7 init function after the constructor for call above function.

ngOnInit() {
  this.getProducts();
}

Add function for the new Angular 7 CDK Drag&Drop.

drop(event: CdkDragDrop<string[]>) {
  moveItemInArray(this.products, event.previousIndex, event.currentIndex);
}

Next, because we will use the new Angular 7 CDK features. We should add modules for it to `src/app/home/home.module.ts` then add this imports.

import { ScrollingModule } from '@angular/cdk/scrolling';
import { DragDropModule } from '@angular/cdk/drag-drop';

Register to `@NgModule` imports array.

imports: [
  IonicModule,
  CommonModule,
  FormsModule,
  ScrollingModule,
  DragDropModule,
  RouterModule.forChild([{ path: '', component: HomePage }])
],

Next, open and edit `src/app/home/home.page.html` then replace all HTML tags with this.

<ion-header>
  <ion-toolbar>
    <ion-title>Home</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <cdk-virtual-scroll-viewport cdkDropList itemSize="20" class="example-viewport" (cdkDropListDropped)="drop($event)">
    <ion-item *cdkVirtualFor="let p of products" class="example-item" href="/tabs/(details:{{p._id}})" cdkDrag>
      <ion-icon name="desktop" slot="start"></ion-icon>
      {{p.prod_name}}
      <div class="item-note" slot="end">
        {{p.prod_price | currency}}
      </div>
    </ion-item>
  </cdk-virtual-scroll-viewport>
</ion-content>


6. Ionic 4, Angular 7 and Cordova Tutorial: Display Data Details and Delete

Every time you click the list item in the List of data, you will be redirect to Details tab including the ID of the selected data. Open and edit `src/app/details/` then add/replace this imports.

import { Component, OnInit } from '@angular/core';
import { LoadingController, AlertController } from '@ionic/angular';
import { ApiService } from '../api.service';
import { ActivatedRoute, Router } from '@angular/router';
import { Product } from '../product';

Inject above modules to the constructor.

constructor(public api: ApiService,
  public loadingController: LoadingController,
  public alertController: AlertController,
  public route: ActivatedRoute,
  public router: Router) {}

Add a variable before the constructor for hold Product data.

product:Product = { _id: null, prod_name: '', prod_desc: '', prod_price: null, updated_at: null };

Add an asynchronous function to getting Product detail from API.

async getProduct() {
  if(this.route.snapshot.paramMap.get('id') == 'null') {
    this.presentAlertConfirm('You are not choosing an item from the list');
  } else {
    const loading = await this.loadingController.create({
      message: 'Loading...'
    });
    await loading.present();
    await this.api.getProduct(this.route.snapshot.paramMap.get('id'))
      .subscribe(res => {
        console.log(res);
        this.product = res;
        loading.dismiss();
      }, err => {
        console.log(err);
        loading.dismiss();
      });
  }
}

Add an asynchronous function for display an alert.

async presentAlertConfirm(msg: string) {
  const alert = await this.alertController.create({
    header: 'Warning!',
    message: msg,
    buttons: [
      {
        text: 'Okay',
        handler: () => {
          this.router.navigate(['']);
        }
      }
    ]
  });

  await alert.present();
}

Call get product function from Angular 7 init function.

ngOnInit() {
  this.getProduct();
}

Add the functions to delete the data.

async delete(id) {
  const loading = await this.loadingController.create({
    message: 'Loading...'
  });
  await loading.present();
  await this.api.deleteProduct(id)
    .subscribe(res => {
      loading.dismiss();
      this.router.navigate([ '/tabs', { outlets: { home: 'home' } } ]);
    }, err => {
      console.log(err);
      loading.dismiss();
    });
}

Next, open and edit `src/app/details/details.page.html` then replace all HTML tags with this.

<ion-header>
  <ion-toolbar>
    <ion-title>Details</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-card>
    <ion-card-header>
      <ion-card-title>{{product.prod_name}}</ion-card-title>
    </ion-card-header>

    <ion-card-content>
      <ion-item>
        <p>Price:</p>
        <p>{{product.prod_price | currency}}</p>
      </ion-item>
      <ion-item>
        <p>Description:</p>
        <p>{{product.prod_desc}}</p>
      </ion-item>
      <ion-button type="button" shape="round" color="primary" expand="block" href="/tabs/(edit:{{product._id}})">Edit</ion-button>
      <ion-button type="button" shape="round" color="danger" expand="block" (click)="delete(product._id)">Delete</ion-button>
    </ion-card-content>
  </ion-card>
</ion-content>


7. Ionic 4, Angular 7 and Cordova Tutorial: Edit and Update Data

We will use Angular 7 Reactive Forms for edit data. Open and edit `src/app/edit/edit.module.ts` then add/replace this imports.

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Register the Reactive Form Module to the `@NgModule` imports array.

imports: [
  IonicModule,
  CommonModule,
  FormsModule,
  ReactiveFormsModule,
  RouterModule.forChild([{ path: '', component: EditPage }])
],

Next, open and edit `src/app/edit/edit.page.ts` then add/replace this imports.

import { Component, OnInit } from '@angular/core';
import { LoadingController, AlertController } from '@ionic/angular';
import { ApiService } from '../api.service';
import { ActivatedRoute, Router } from '@angular/router';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { Product } from '../product';

Add this constructor and inject above modules.

constructor(public api: ApiService,
  public loadingController: LoadingController,
  public alertController: AlertController,
  public route: ActivatedRoute,
  public router: Router,
  private formBuilder: FormBuilder) {
}

Add the variables for hold current data, Form Group and Reactive Form controls.

productForm: FormGroup;
_id:any='';
prod_name:string='';
prod_desc:string='';
prod_price:number=null;

Add asynchronous function to get Product Detail.

async getProduct(id) {
  if(this.route.snapshot.paramMap.get('id') == 'null') {
    this.presentAlertConfirm('You are not choosing an item from the list');
  } else {
    const loading = await this.loadingController.create({
      message: 'Loading...'
    });
    await loading.present();
    await this.api.getProduct(id)
      .subscribe(data => {
        this._id = data._id;
        this.productForm.setValue({
          prod_name: data.prod_name,
          prod_desc: data.prod_desc,
          prod_price: data.prod_price
        });
        loading.dismiss();
      }, err => {
        console.log(err);
        loading.dismiss();
      });
  }
}

Call that function inside Angular 7 init.

ngOnInit() {
  this.getProduct(this.route.snapshot.params['id']);
  this.productForm = this.formBuilder.group({
    'prod_name' : [null, Validators.required],
    'prod_desc' : [null, Validators.required],
    'prod_price' : [null, Validators.required]
  });
}

Add asynchronous function for handle form submit.

async onFormSubmit(form:NgForm) {
  await this.api.updateProduct(this._id, form)
    .subscribe(res => {
        let id = res['_id'];
        this.router.navigate([ '/tabs', { outlets: { details: id }} ]);
      }, (err) => {
        console.log(err);
      }
    );
}

Add asynchronous function to display an alert that calls on the first function.

async presentAlertConfirm(msg: string) {
  const alert = await this.alertController.create({
    header: 'Warning!',
    message: msg,
    buttons: [
      {
        text: 'Okay',
        handler: () => {
          this.router.navigate(['']);
        }
      }
    ]
  });

  await alert.present();
}

Next, open and edit `src/app/edit/edit.page.html` then replace all HTML tags with this.

<ion-header>
  <ion-toolbar>
    <ion-title>Edit</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <form [formGroup]="productForm" (ngSubmit)="onFormSubmit(productForm.value)">
    <ion-item>
      <ion-label position="floating">Product Name</ion-label>
      <ion-input type="text" formControlName="prod_name"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label position="floating">Product Price</ion-label>
      <ion-input type="number" formControlName="prod_price"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label position="stacked">Product Description</ion-label>
      <ion-textarea formControlName="prod_desc"></ion-textarea>
    </ion-item>
    <ion-button type="submit" shape="round" color="primary" expand="block" [disabled]="!productForm.valid">Submit</ion-button>
  </form>
</ion-content>


8. Ionic 4, Angular 7 and Cordova Tutorial: Add Data

Almost same with edit data, we will create a form for add new data. Open and edit `src/app/add/add.module.ts` then add/replace this imports.

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Register the Reactive Form Module to the `@NgModule` imports array.

imports: [
  IonicModule,
  CommonModule,
  FormsModule,
  ReactiveFormsModule,
  RouterModule.forChild([{ path: '', component: AddPage }])
],

Next, open and edit `src/app/edit/edit.page.ts` then add/replace this imports.

import { Component, OnInit } from '@angular/core';
import { LoadingController, AlertController } from '@ionic/angular';
import { ApiService } from '../api.service';
import { ActivatedRoute, Router } from '@angular/router';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { Product } from '../product';

Add this constructor and inject above modules.

constructor(public api: ApiService,
  public loadingController: LoadingController,
  public alertController: AlertController,
  public route: ActivatedRoute,
  public router: Router,
  private formBuilder: FormBuilder) {
}

Add the variables for hold current data, Form Group and Reactive Form controls.

productForm: FormGroup;
prod_name:string='';
prod_desc:string='';
prod_price:number=null;

Add Angular 7 init.

ngOnInit() {
  this.productForm = this.formBuilder.group({
    'prod_name' : [null, Validators.required],
    'prod_desc' : [null, Validators.required],
    'prod_price' : [null, Validators.required]
  });
}

Add asynchronous function for handle form submit.

async onFormSubmit(form:NgForm) {
  const loading = await this.loadingController.create({
    message: 'Loading...'
  });
  await loading.present();
  await this.api.addProduct(form)
    .subscribe(res => {
        let id = res['_id'];
        loading.dismiss();
        console.log(this.router);
        this.router.navigate([ { outlets: { details: id } } ], { relativeTo: this.route.parent });
      }, (err) => {
        console.log(err);
        loading.dismiss();
      });
}

Next, open and edit `src/app/edit/edit.page.html` then replace all HTML tags with this.

<ion-header>
  <ion-toolbar>
    <ion-title>
      Add Product
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <form [formGroup]="productForm" (ngSubmit)="onFormSubmit(productForm.value)">
    <ion-item>
      <ion-label position="floating">Product Name</ion-label>
      <ion-input type="text" formControlName="prod_name"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label position="floating">Product Price</ion-label>
      <ion-input type="number" formControlName="prod_price"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label position="floating">Product Description</ion-label>
      <ion-textarea formControlName="prod_desc"></ion-textarea>
    </ion-item>
    <ion-button type="submit" shape="round" color="primary" expand="block" [disabled]="!productForm.valid">Submit</ion-button>
  </form>
</ion-content>


9. Ionic 4, Angular 7 and Cordova Tutorial: Run and Test The App

Before running the Ionic 4 and Angular 7 application, first, you have run the Node.js, Express.js and MongoDB RESTful API that previously downloaded. Type this commands in another terminal tab. We assume, you already running the MongoDB server.

npm install
npm start

Now, we have to run the whole Ionic 4 and Angular 7 application to the browser first by type this command.

ionic serve -l

You can navigate the whole application, so it will similar like this.

Ionic 4, Angular 7 and Cordova Tutorial: Build CRUD Mobile Apps - Test and Run

To run on the devices, type this commands.

ionic cordova platform rm android
ionic cordova platform add android
ionic cordova run android
ionic cordova platform rm ios
ionic cordova platform add ios
ionic cordova run ios

That it's, the results of our experiment of using Angular 7 with Ionic 4 beta. To get the full working source code, you can get from our GitHub.

We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ion2FullApp ELITE - The Complete Ionic 3 Starter App and save development and design time.

That just the basic. If you need more deep learning about Ionic, Angular, and Typescript, you can find the following books:

Or take the following course:

Thanks!

The following resources might be useful for you:

Loading…