This post is about displaying the API records with delete and update actions using new Ionic and Angular reactive programming. This is a continuation of Ionic Angular series and it explains to you how to distribute the data between the components using RxJS method like BehaviorSubject. All of the feed API responses/records storing in a reactive object, This help the application DOM works seamlessly with update and delete operations. Implement this to your side project and enrich your applications.
Live Demo
Video Tutorial
VIDEO[embedded content]
Feed Service
Create a Feed service for maintaining all of the data operations like display, update and delete
new-ionic-angular$ ionic g s services/feed
> ng generate service services/feed
CREATE src/app/services/feed.service.spec.ts (323 bytes)
CREATE src/app/services/feed.service.ts (133 bytes)
[OK] Generated service!
feed.service.ts
Here feedData method connects with API. feedData$ is a behavior subject RxJS reactive storage object, this helps you distribute the data between the components. changeFeedData method updates the reactive object value using next() .
import { Injectable } from ‘@angular/core’ ;
import { BehaviorSubject , Observable } from ‘rxjs’ ;
import { HttpService } from ‘./http.service’ ;
@Injectable ({
providedIn: ‘root’
export class FeedService {
feedData$ = new BehaviorSubject <any>([]);
constructor ( private httpService : HttpService ) {}
changeFeedData (data : any ) {
this . feedData$ . next (data);
feedData (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feed’ , postData);
Feed Page – feed.page.ts
Import the Feed service and on page initiate(ngOnInit ) make the feed API call to get the records. Construct the postData object with login user id and token values. Storing the API results in feedData$ reactive object using feedService.changeFeedData method.
import { Component , OnInit } from ‘@angular/core’ ;
import { FeedService } from ‘src/app/services/feed.service’ ;
import { AuthService } from ‘./../../services/auth.service’ ;
import { ToastService } from ‘./../../services/toast.service’ ;
@Component ({
selector: ‘app-feed’ ,
templateUrl: ‘./feed.page.html’ ,
styleUrls: [ ‘./feed.page.scss’ ]
export class FeedPage implements OnInit {
public authUser : any ;
postData = {
user_id : ” ,
token : ”
constructor (
private auth : AuthService ,
private feedSerive : FeedService ,
private toastService : ToastService
ngOnInit () {
this . auth . userData$ . subscribe ((res : any ) => {
this . authUser = res;
this . getFeedData ();
});
getFeedData () {
this . postData . user_id = this . authUser . uid ;
this . postData . token = this . authUser . token ;
if ( this . postData . user_id && this . postData . token ) {
this . feedSerive . feedData ( this . postData ). subscribe (
(res : any ) => {
this . feedSerive . changeFeedData ( res . feedData );
},
(error : any ) => {
this . toastService . presentToast ( ‘Network Issue.’ );
}
);
Display Data
Generate a component for displaying feed records.
$ ionic g c components/feedCard
> ng generate component components/feedCard
CREATE src/app/components/feed-card/feed-card.component.scss (0 bytes)
CREATE src/app/components/feed-card/feed-card.component.html (28 bytes)
CREATE src/app/components/feed-card/feed-card.component.spec.ts (741 bytes)
CREATE src/app/components/feed-card/feed-card.component.ts (279 bytes)
[OK] Generated component!
components.module.ts
Declare and export the module for application use.
import { CommonModule } from ‘@angular/common’ ;
import { NgModule } from ‘@angular/core’ ;
import { FormsModule } from ‘@angular/forms’ ;
import { IonicModule } from ‘@ionic/angular’ ;
import { FeedCardComponent } from ‘./feed-card/feed-card.component’ ;
import { SlidesComponent } from ‘./slides/slides.component’ ;
import { StartButtonComponent } from ‘./start-button/start-button.component’ ;
@NgModule ({
declarations: [SlidesComponent, StartButtonComponent, FeedCardComponent],
exports: [SlidesComponent, StartButtonComponent, FeedCardComponent],
imports: [CommonModule, FormsModule, IonicModule]
export class ComponentsModule {}
feed.moudle.ts
Import the components module for accessing the components.
a
import { CommonModule } from ‘@angular/common’ ;
import { NgModule } from ‘@angular/core’ ;
import { FormsModule } from ‘@angular/forms’ ;
import { RouterModule , Routes } from ‘@angular/router’ ;
import { IonicModule } from ‘@ionic/angular’ ;
import { ComponentsModule } from ‘./../../components/components.module’ ;
import { FeedPage } from ‘./feed.page’ ;
const routes : Routes = [
path: ” ,
component: FeedPage
@NgModule ({
imports: [
CommonModule,
ComponentsModule,
FormsModule,
IonicModule,
RouterModule . forChild (routes)
declarations: [FeedPage]
export class FeedPageModule {}
feed.page.html
Include the feedCard(app-feed-card ) component in feed page.
< ion-header >
< ion-toolbar >
< ion-title > Feed</ ion-title >
</ ion-toolbar >
</ ion-header >
< ion-content >
< ion-item >
< h2 > Welcome to </ h2 >
</ ion-item >
< app-feed-card ></ app-feed-card >
</ ion-content >
feed-card.component.html
Design with ionic components.
< ion-card >
< ion-card-content >
feed content
</ ion-card-content >
</ ion-card >
Display Records from Reactive Object
feed-card.component.ts
Subscribe the feedData$ objects for feed records.
import { Component , OnInit } from ‘@angular/core’ ;
import { FeedService } from ‘./../../services/feed.service’ ;
@Component ({
selector: ‘app-feed-card’ ,
templateUrl: ‘./feed-card.component.html’ ,
styleUrls: [ ‘./feed-card.component.scss’ ]
export class FeedCardComponent implements OnInit {
feedData : any ;
constructor ( private feedSerivce : FeedService ) {}
ngOnInit () {
this . feedSerivce . feedData$ . subscribe ((res : any ) => {
this . feedData = res;
});
feed-card.component.html
Bind with HTML and iterate the feed data.
< ion-card *ngFor = “let feed of feedData; let i = index” >
< ion-card-content [innerHTML] = “feed.feed” >
</ ion-card-content >
</ ion-card >
Delete Records
Alert Service
Generate the alert service for confirming the record delete action.
new-ionic-angular$ ionic g s services/alert
> ng generate service services/alert
CREATE src/app/services/alert.service.spec.ts (328 bytes)
CREATE src/app/services/alert.service.ts (134 bytes)
[OK] Generated service!
alert.service.ts
Import the ionic component and modify the presentAlertConfirm method with dynamic inputs. This way you can reuse for other actions.
import { Injectable } from ‘@angular/core’ ;
import { AlertController } from ‘@ionic/angular’ ;
@Injectable ({
providedIn: ‘root’
export class AlertService {
constructor ( public alertController : AlertController ) {}
async presentAlertConfirm (header : string , message : string ) {
let choice;
const alert = await this . alertController . create ({
header : header,
message : message,
buttons : [
{
text : ‘Cancel’ ,
role : ‘cancel’
},
{
text : ‘Okay’ ,
role : ‘okay’
}
]
});
await alert . present ();
await alert . onDidDismiss (). then (data => {
choice = data;
});
return choice;
feed.service.ts
Now include the feedDelete API post request method. Here deleteFeedData method remove the object from the reactive object feedData$
import { Injectable } from ‘@angular/core’ ;
import { BehaviorSubject , Observable } from ‘rxjs’ ;
import { HttpService } from ‘./http.service’ ;
@Injectable ({
providedIn: ‘root’
export class FeedService {
feedData$ = new BehaviorSubject <any>([]);
constructor ( private httpService : HttpService ) {}
changeFeedData (data : any ) {
this . feedData$ . next (data);
getCurrentFeedData () {
return this . feedData$ . getValue ();
deleteFeedData (msgIndex : number ) {
let data = [];
let currentFeedData = this . getCurrentFeedData ();
currentFeedData . splice (msgIndex, 1 );
let newFeedUpdateData = data . concat (currentFeedData);
this . changeFeedData (newFeedUpdateData);
feedData (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feed’ , postData);
feedDelete (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feedDelete’ , postData);
feed-card.components.ts
Create a feedDeleteAction and connect with feedDelete API with alert confirm action. Then delete the record from the behavior subject.
import { Component , Input , OnInit } from ‘@angular/core’ ;
import { AlertService } from ‘./../../services/alert.service’ ;
import { FeedService } from ‘./../../services/feed.service’ ;
@Component ({
selector: ‘app-feed-card’ ,
templateUrl: ‘./feed-card.component.html’ ,
styleUrls: [ ‘./feed-card.component.scss’ ]
export class FeedCardComponent implements OnInit {
@ Input () loginUser : any ;
feedData : any ;
postData = {
user_id : ” ,
token : ”
constructor (
private feedSerivce : FeedService ,
private alertSerivce : AlertService
ngOnInit () {
this . feedSerivce . feedData$ . subscribe ((res : any ) => {
this . feedData = res;
});
feedDeleteAction (msgIndex : number ) {
this . postData . user_id = this . loginUser . user_id ;
this . postData . token = this . loginUser . token ;
this . alertSerivce
. presentAlertConfirm ( ‘Delete feed’ , ‘Do you want to delete this feed?’ )
. then ((res : any ) => {
if ( res . role === ‘okay’ ) {
this . feedSerivce . feedDelete ( this . postData ). subscribe ((res : any ) => {
if ( res . success ) {
this . feedSerivce . deleteFeedData (msgIndex);
}
});
}
});
feed-card.components.html
Bind the action with delete button.
< ion-card *ngFor = “let feed of feedData; let i = index” >
< ion-card-content >
< button (click) = “feedDeleteAction(i)” class = “right” >
< ion-icon name = “trash” ></ ion-icon >
</ button >
< p [innerHTML] = “feed.feed” ></ p >
</ ion-card-content >
</ ion-card >
Update Feed
feed.server.ts
Add methods for feedUpdate to connect RESTful API. Push the feed data using updateFeedData().
import { Injectable } from ‘@angular/core’ ;
import { BehaviorSubject , Observable } from ‘rxjs’ ;
import { HttpService } from ‘./http.service’ ;
@Injectable ({
providedIn: ‘root’
export class FeedService {
feedData$ = new BehaviorSubject <any>([]);
constructor ( private httpService : HttpService ) {}
changeFeedData (data : any ) {
this . feedData$ . next (data);
getCurrentFeedData () {
return this . feedData$ . getValue ();
updateFeedData (newFeed : any ) {
let data = [];
data . push (newFeed);
let currentFeedData = this . getCurrentFeedData ();
let newFeedUpdateData = data . concat (currentFeedData);
this . changeFeedData (newFeedUpdateData);
deleteFeedData (msgIndex : number ) {
let data = [];
let currentFeedData = this . getCurrentFeedData ();
currentFeedData . splice (msgIndex, 1 );
let newFeedUpdateData = data . concat (currentFeedData);
this . changeFeedData (newFeedUpdateData);
feedData (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feed’ , postData);
feedDelete (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feedDelete’ , postData);
feedUpdate (postData : any ) : Observable <any> {
return this . httpService . post ( ‘feedUpdate’ , postData);
Feed Update Component
Generate a component for feed update operations.
new-ionic-angular$ ionic g c components/feed-update
> ng generate component components/feed-update
CREATE src/app/components/feed-update/feed-update.component.scss (0 bytes)
CREATE src/app/components/feed-update/feed-update.component.html (30 bytes)
CREATE src/app/components/feed-update/feed-update.component.spec.ts (755 bytes)
CREATE src/app/components/feed-update/feed-update.component.ts (287 bytes)
[OK] Generated component!
feed-update.component.ts
Import the feed service and follow the same like feedDelete action. Construct the postData value with text
a
import { Component , Input , OnInit } from ‘@angular/core’ ;
import { FeedService } from ‘./../../services/feed.service’ ;
@Component ({
selector: ‘app-feed-update’ ,
templateUrl: ‘./feed-update.component.html’ ,
styleUrls: [ ‘./feed-update.component.scss’ ]
export class FeedUpdateComponent implements OnInit {
@ Input () loginUser : any ;
public postData = {
feed : ” ,
feed_id : ” ,
lastCreated : ” ,
token : ” ,
user_id : ”
constructor ( private feedService : FeedService ) {}
ngOnInit () {}
feedUpdateAction () {
if ( this . postData . feed . length > 0 ) {
this . postData . lastCreated = ” ;
this . postData . user_id = this . loginUser . user_id ;
this . postData . token = this . loginUser . token ;
this . feedService . feedUpdate ( this . postData ). subscribe ((res : any ) => {
this . postData . feed = ” ;
this . feedService . updateFeedData ( res . feedData );
});
feed-update.component.html
Bind the postData value with ion-textarea. Connect the feedUpdateAction with update button.
< ion-item >
< ion-textarea placeholder = “Enter more information here…” [(ngModel)] = “postData.feed” ></ ion-textarea >
</ ion-item >
< ion-item >
< ion-button color = ‘mango’ item-end (click) = “feedUpdateAction()” > Update</ ion-button >
</ ion-item > a
Timeago
Install the Time Ago pipe.
$npm install time-ago-pipe –save
Create web component for timego.
new-ionic-angular$ ionic g c components/timeago
> ng generate component components/timeago
CREATE src/app/components/timeago/timeago.component.scss (0 bytes)
CREATE src/app/components/timeago/timeago.component.html (26 bytes)
CREATE src/app/components/timeago/timeago.component.spec.ts (733 bytes)
CREATE src/app/components/timeago/timeago.component.ts (272 bytes)
[OK] Generated component!
components.module.ts
Import all of the newly generated components feedUpdate, timeAgo and TimeAgoPipe.
import { CommonModule } from ‘@angular/common’ ;
import { NgModule } from ‘@angular/core’ ;
import { FormsModule } from ‘@angular/forms’ ;
import { IonicModule } from ‘@ionic/angular’ ;
import { TimeAgoPipe } from ‘time-ago-pipe’ ;
import { FeedCardComponent } from ‘./feed-card/feed-card.component’ ;
import { FeedUpdateComponent } from ‘./feed-update/feed-update.component’ ;
import { SlidesComponent } from ‘./slides/slides.component’ ;
import { StartButtonComponent } from ‘./start-button/start-button.component’ ;
import { TimeagoComponent } from ‘./timeago/timeago.component’ ;
@NgModule ({
declarations: [
SlidesComponent,
StartButtonComponent,
FeedCardComponent,
FeedUpdateComponent,
TimeagoComponent,
TimeAgoPipe
exports: [
SlidesComponent,
StartButtonComponent,
FeedCardComponent,
FeedUpdateComponent,
TimeagoComponent
imports: [CommonModule, FormsModule, IonicModule]
export class ComponentsModule {}
timeago.component.ts
Using @input retrieve the created value from the feed loop. Convert the Unix timestamp to date format.
a
import { Component , OnInit , Input } from ‘@angular/core’ ;
@Component ({
selector: ‘app-timeago’ ,
templateUrl: ‘./timeago.component.html’ ,
styleUrls: [ ‘./timeago.component.scss’ ],
export class TimeagoComponent implements OnInit {
@ Input () created : any ;
newTime : any ;
constructor () { }
ngOnInit () {
this . newTime = this . converTime ( this . created );;
converTime (time : any ) {
let a = new Date (time * 1000 );
return a;
timeago.component.html
Apply the timeAgo pipe.
feed-card.component.html
Now connect the app-timeago component with HTML.
< ion-card *ngFor = “let feed of feedData; let i = index” >
< ion-card-content >
< button (click) = “feedDeleteAction(i, feed.feed_id)” class = “right” >
< ion-icon name = “trash” ></ ion-icon >
</ button >
< p [innerHTML] = “feed.feed” ></ p >
< app-timeago [created] = “feed.created” ></ app-timeago >
</ ion-card-content >
</ ion-card >
Building a Mobile Application
You have to create a production build for generating mobile applications.
Production Build
$ ionic build –prod
Build iOS App
Following commands for executing Xcode build, watch the video tutorial you will understand more.
$ npm run ios-add
$ npm run ios-open
Build Android App
Open Android build using Android SDK
$ npm run android-add
$ npm run android-open
Project Updates
If you want to update your project changes.
$ npm run ios-copy
$ npm run android-copy
No comments:
Post a Comment