圖1 點選清單項目,必須傳遞參數到「細節」頁面,如"id:2330"。 |
this.navCtrl.push(DetailPage, { id: 2330, arg: some_value });
而接收端—即「細節」頁面—則必須透過NavParams元件的協助,以NavParams提供的get()讀取資料:
import { NavController, NavParams } from 'ionic-angular'; ... export class DetailPage { id=0; constructor(public navCtrl: NavController, public navParams: NavParams) { this.id = this.navParams.get('id'); } ...範例專案
首先建立新專案,並建立新頁面detail。原本的home頁面將用來顯示清單,而點選清單項目後,則會跳至detail頁面,顯示細節:
ionic start listApp blank cd listApp ionic g page detail --no-module另外,由於清單與細節會共用同一組陣列資料,資料部份使用provider,讓兩個頁面可以共用,因此還必須建立提供資料的provider:
ionic g provider data建完之後,專案架構如下圖:
圖2 專案架構圖:兩個頁面detail與home,另有data provider。 |
1.1 修正app.module.ts:加入HttpClientModule
ionic CLI產生provider時,會建立一個ts檔(此例為providers/data/data.ts),並自動修改app.module.ts。data.ts程式碼如下:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable() export class DataProvider { constructor(public http: HttpClient) { console.log('Hello DataProvider Provider'); } }
- 第2~4行:Injectable為Angular Service元件必須使用之decorator,因此第2行import,第4行加上@Injectable decorator,讓此元件成為可被注入(inject)之服務。
- 第5行:provider元件之類別名稱為DataProvider。若檢視app.module.ts,便會看到CLI已自動將此元件加入app.module.ts:
... import { DataProvider } from '../providers/data/data'; @NgModule({ ... providers: [ ..., DataProvider ]
上述data.ts以及自動修改的app.module.ts看似已符合Angular Service元件寫法,後續可將DataProvider注入其他元件使用。然而執行時,卻會出現錯誤訊息,此因目前最新之ionic CLI版本(3.20.0)並未正確補足app.module.ts裡面的定義。
檢視data.ts的第1與第6行都用到了HttpClient元件,然而app.module.ts並不知道要去何處載入HttpClient元件來使用,因此,必須先import HttpClientModule—也就是HttpClient所屬之模組到AppModule裡,故修正app.module.ts如下,將HttpClientModule import進來,並加入模組的imports屬性裡:
import { HttpClientModule } from '@angular/common/http';... @NgModule({ ... imports: [ BrowserModule, HttpClientModule, IonicModule.forRoot(MyApp) ],
1.2 撰寫DataProvider
由於DataProvider只須提供兩個頁面共用資料,因此,只須在data.ts裡定義一個常數陣列,再加上讀取陣列全部元素(用於清單顯示)、以及讀取特定元素(用於顯示特定項目細節)兩個methods即可。完整之data.ts如下:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; export const DATA=[ {id: 2330, name: '台積電', price: 147.0, PER: 14.44, PBR: 3.65, yield: 3.06, Desc: '晶圓製造'}, {id: 1301, name: '台塑', price: 76.5, PER: 27.03, PBR: 1.7, yield: 2.22, Desc: '聚氯乙烯(PVC)、氯乙烯等塑膠製品'}, {id: 2002, name: '中鋼', price: 25.8, PER: 18.04, PBR: 1.33, yield: 3.88, Desc: '鋼品設計製造買賣儲運及其他相關業務'}, {id: 3045, name: '台灣大', price: 108.0, PER: 19.42, PBR: 6.13, yield: 5.19, Desc: '通訊業'}, {id: 2454, name: '聯發科', price: 421.5, PER: 14.03, PBR: 2.68, yield: 3.56, Desc: '多媒體IC 、電腦週邊IC、其他IC'}, {id: 2317, name: '鴻海', price: 93.1, PER: 10.52, PBR: 1.48, yield: 1.93, Desc: '電腦系統設備連接器等之開發設計製造'}, {id: 3008, name: '大立光', price: 2695.0, PER: 18.6, PBR: 7.83, yield: 1.06, Desc: '各式光學鏡頭模組研發設計生產銷售'} ]; @Injectable() export class DataProvider { lists = DATA; constructor(public http: HttpClient) { console.log('Hello DataProvider Provider'); } /* 回傳所有項目 */ getLists(){ return this.lists; } /* 回傳單一項目 */ getItem(id){ return this.lists.filter(x => x.id == id)[0]; } }
- 第4-19行:定義共用的常數資料陣列DATA。每個元素有id, name, price, PER, PBR, yield, Desc等屬性。
- 第22行:定義DataProvider的屬性lists,讓其等於常數陣列DATA,以便提供存取DATA陣列內容的服務。
- 第27-29行:取得陣列所有元素。
- 第31-33行:取得id所屬的某個陣列元素。this.lists.filter()為typescript的陣列過濾函式,x為iterator,依序處理陣列每一個元素,因此符合x.id與傳進來的參數id相等的陣列元素,便會過濾出來。而因DATA陣列id值都是唯一,故回傳過濾結果的第一個元素(即[0])。
2.1 撰寫清單頁面:HomePage元件
清單頁面從DataProvider取得陣列所有元素,加以顯示。另外,每個清單項目必須加上click事件處理:當點選時,push「細節元件」進瀏覽堆疊,同時也有附上id值作為參數。home.ts程式碼如下:import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { DetailPage } from '../detail/detail'; import { DataProvider } from '../../providers/data/data'; @Component({ selector: 'page-home', templateUrl: 'home.html', }) export class HomePage { lists=[]; constructor(public navCtrl: NavController, public dp: DataProvider) { this.lists = this.dp.getLists(); } showDetail(id){ this.navCtrl.push( DetailPage, { id: id } ); } }
- 第4-5行:import兩個所需元件。DataProvider即提供資料服務的元件。
- 第14行:在constructor中設定DataProvider引數dp,以便透過dp取得資料服務。
- 第15行:透過dp呼叫getLists()服務(在data.ts內),取得DATA陣列內容,設定給屬性lists。
- 第17-21行:滑鼠點選清單各個項目時的處理函式。函式中呼叫this.navCtrl.push()設定瀏覽堆疊(navigation stack)最上層頁面-DetailPage,push()第二個引數便是傳送給DetailPage的參數。此處傳送的物件有一個id屬性,其數值則為showDetail(id)傳送進來的數值,該數值會在home.html內設定。
home.html頁面如下,除了使用ion-list排列清單外,在每個清單項目ion-item處,則必須設定滑鼠點選事件(click),讓其呼叫showDetail(),並將參數設定為自己這個項目的id值(如第11行的item.id):
<ion-header> <ion-navbar> <ion-title> Demo: 傳遞資料 </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-item *ngFor="let item of lists" (click)="showDetail(item.id)"> {{ item.id }} {{ item.name }} </ion-item> </ion-list> </ion-content>
2.2 撰寫細節頁面:DetailPage
因DetailPage建立時,帶有--no-module參數,因此,必須先將DetailPage元件加入AppModule中,亦即修改app.module.ts,import DetailPage,並將DetailPage元件加入模組的declarations與entryComponents屬性中:
... import { DetailPage } from '../pages/detail/detail'; ... @NgModule({ declarations: [ MyApp, HomePage, DetailPage ], ... entryComponents: [ MyApp, HomePage, DetailPage ],DetailPage也會使用DataProvider的資料存取服務,同樣要import DataProvider,並在constructor中設定DataProvider引數。detail.ts程式碼如下:
import { Component } from '@angular/core'; import { NavController, NavParams } from 'ionic-angular'; import { DataProvider } from '../../providers/data/data'; @Component({ selector: 'page-detail', templateUrl: 'detail.html', }) export class DetailPage { id=0; data={}; constructor(public navCtrl: NavController, public navParams: NavParams, public ds: DataProvider ) { this.id = this.navParams.get('id'); this.data = this.ds.getItem(this.id); } ionViewDidLoad() { console.log('ionViewDidLoad DetailPage'); } }
- 第2,12行:和HomePage不同在於DetailPage要接收傳送過來的參數,因此要import NavParams元件,並在constructor中設定NavParams引數,透過該引數,才能讀取前一頁面傳送過來的參數。
- 第15行:NavParams物件提供get()函式,指定屬性名稱,例如get('id'),便能讀取HomePage傳送參數中的id欄位值。
- 第16行:取得DATA陣列中this.id值所指定的陣列元素。
detail.html以ion-card製作卡片式頁面,可參考ionic官網文件,關於ion-card的說明。detail.html程式碼如下:
<ion-header> <ion-navbar> <ion-title> {{data.name}} </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-card> <ion-item> <ion-icon name="wine" item-left large></ion-icon> <h3> {{ data.id}} {{data.name}}</h3> <p>{{ data.Desc }}</p> </ion-item> <ion-item> <span item-left>股價{{data.price}}</span> <span item-left>本益比{{data.PER}}</span> </ion-item> </ion-card> </ion-content>
最後,完整專案可參考https://github.com/leuowang/ionic-App.git裡之listApp資料夾。
沒有留言:
張貼留言