这篇文章是关于使用新的Ionic和Angular反应式编程显示具有删除和更新操作的API记录的。这是Ionic Angular系列的延续,它向您说明了如何使用RxJS方法(例如BehaviorSubject)在组件之间分配数据。所有提要API响应/记录都存储在反应式对象中,这有助于应用程序DOM与更新和删除操作无缝协作。将此实现到您的辅助项目中,并丰富您的应用程序。
Feed Service Create a Feed service for maintaining all of the data operations like display, update and deletenew-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([]); constructor(private httpService: HttpService) {} changeFeedData(data: any) { this.feedData$.next(data); } feedData(postData: any): Observable { 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. aimport { 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. Feed feed-card.component.html Design with ionic components. Welcome to {{ authUser?.name }}
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. feed content 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 ([]); 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 { return this.httpService.post('feed', postData); } feedDelete(postData: any): Observable { 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. 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 ([]); 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 { return this.httpService.post('feed', postData); } feedDelete(postData: any): Observable { return this.httpService.post('feedDelete', postData); } feedUpdate(postData: any): Observable { 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 aimport { 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. 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. aimport { 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. Update {{newTime | timeAgo}}feed-card.component.html Now connect the app-timeago component with HTML.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