Ionic 4, Angular 7 and Cordova Tutorial: Build CRUD Mobile Apps
Another 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 hybrid Mobile Apps. For the backend, we are using our existing Node, Express.js, and MongoDB RESTful API. There are few new features in Angular 7, but we just take a bit 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.
1 |
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.
1 2 |
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.
1 |
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.
1 |
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.
1 |
Install the free Ionic Pro SDK and connect your app? (Y/n) N |
Next, go to the newly created app folder.
1 |
cd ./ionic4-angular7-crud |
You will see the Angular version still using 6 in the package.json
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
"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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
"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.
1 2 |
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
.
1 2 |
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.
2. Ionic 4, Angular 7 and Cordova Tutorial: Install Material and CDK
To install Angular 7 Material and CDK, simply run this command.
1 |
ng add @angular/material |
Type enter or yes for every question that showed up.
1 2 3 4 |
? 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.
1 2 3 4 5 6 7 8 9 10 11 12 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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.
1 2 |
import FormsModule from '@angular/forms'; import HttpClientModule from '@angular/common/http'; |
Add it to @NgModule
imports after BrowserModule
.
1 2 3 4 5 6 |
imports: [ Â BrowserModule, Â FormsModule, Â HttpClientModule, Â AppRoutingModule ], |
We will use the 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.
1 2 3 4 5 6 7 |
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.
1 |
ng g service api |
Next, open and edit src/app/api.service.ts
then add these imports.
1 2 3 4 |
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
.
1 2 3 4 |
const httpOptions = Â headers: new HttpHeaders('Content-Type': 'application/json') ; const apiUrl = "/api/v1/products"; |
Inject the HttpClient
module to the constructor.
1 |
constructor(private http: HttpClient) |
Add the error handler function.
1 2 3 4 5 6 7 8 9 10 |
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 product data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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 the 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.
1 |
ionic g page details |
Next, open and edit src/app/tabs/tabs.router.module.ts
then replace and add these imports.
1 2 3 4 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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 these imports.
1 2 3 4 |
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
import array.
1 2 3 4 5 6 7 8 9 10 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<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="http://www.djamware.com/tabs/(home:home)"> Â Â Â <ion-icon name="home"></ion-icon> Â Â Â <ion-label>Home</ion-label> Â Â </ion-tab-button> Â Â <ion-tab-button tab="details" href="http://www.djamware.com/tabs/(details:null)"> Â Â Â <ion-icon name="eye"></ion-icon> Â Â Â <ion-label>Details</ion-label> Â Â </ion-tab-button> Â Â <ion-tab-button tab="add" href="http://www.djamware.com/tabs/(add:add)"> Â Â Â <ion-icon name="add"></ion-icon> Â Â Â <ion-label>Add</ion-label> Â Â </ion-tab-button> Â Â <ion-tab-button tab="edit" href="http://www.djamware.com/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.
1 2 3 4 5 6 |
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.
1 2 3 4 |
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.
1 |
products: Product[] = []; |
Add function for getting Product list from API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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.
1 2 3 |
ngOnInit() Â this.getProducts(); |
Add function for the new Angular 7 CDK Drag&Drop.
1 2 3 |
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 these imports.
1 2 |
import ScrollingModule from '@angular/cdk/scrolling'; import DragDropModule from '@angular/cdk/drag-drop'; |
Register to @NgModule
import array.
1 2 3 4 5 6 7 8 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<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="http://www.djamware.com/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    </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 redirected to the Details tab including the ID of the selected data. Open and edit src/app/details/
then add/replace this imports.
1 2 3 4 5 |
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 the above modules to the constructor.
1 2 3 4 5 |
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.
1 |
product:Product = _id: null, prod_name: '', prod_desc: '', prod_price: null, updated_at: null ; |
Add an asynchronous function to getting Product detail from API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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 to display an alert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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.
1 2 3 |
ngOnInit() Â this.getProduct(); |
Add the functions to delete the data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<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 </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="http://www.djamware.com/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 these imports.
1 |
import FormsModule, ReactiveFormsModule from '@angular/forms'; |
Register the Reactive Form Module to the @NgModule
import array.
1 2 3 4 5 6 7 |
imports: [ Â IonicModule, Â CommonModule, Â FormsModule, Â ReactiveFormsModule, Â RouterModule.forChild([ path: '', component: EditPage ]) ], |
Next, open and edit src/app/edit/edit.page.ts
then add/replace these imports.
1 2 3 4 5 6 |
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 the above modules.
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 |
productForm: FormGroup; _id:any=''; prod_name:string=''; prod_desc:string=''; prod_price:number=null; |
Add asynchronous function to get Product Detail.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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.
1 2 3 4 5 6 7 8 |
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.
1 2 3 4 5 6 7 8 9 10 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<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 the same with edit data, we will create a form to add new data. Open and edit src/app/add/add.module.ts
then add/replace these imports.
1 |
import FormsModule, ReactiveFormsModule from '@angular/forms'; |
Register the Reactive Form Module to the @NgModule
import array.
1 2 3 4 5 6 7 |
imports: [ Â IonicModule, Â CommonModule, Â FormsModule, Â ReactiveFormsModule, Â RouterModule.forChild([ path: '', component: AddPage ]) ], |
Next, open and edit src/app/edit/edit.page.ts
then add/replace these imports.
1 2 3 4 5 6 |
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 the above modules.
1 2 3 4 5 6 7 |
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.
1 2 3 4 |
productForm: FormGroup; prod_name:string=''; prod_desc:string=''; prod_price:number=null; |
Add Angular 7 init.
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<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.
1 2 |
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.
1 |
ionic serve -l |
You can navigate the whole application, so it will similar like this.
To run on the devices, type these commands.
1 2 3 4 5 6 |
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 |