เนื้อหาต่อไปนี้ เราจะมาดูแนวทางการแสดงช้อมูลแบบ card โดยใช้ card component
แต่จะไม่ขอลงรายละเอียด เกี่ยวกับรูปแบบของ card สามารถเข้าไปดูการปรับแต่งเพิ่มเติม
ด้วยตนเองได้ที่ลิ้งค์ด้านล่าง
เตรียม Service API อย่างง่าย
การแสดงข้อมูลแบบ card นั้น เราจะใช้ข้อมูลจากการใช้ service provider ไปดึงข้อมูลบนฝั่ง
server ผ่าน service api ที่เตรียมไว้ ในที่นี้ จะใช้ข้อมูลจากเว็บไซต์ www.ninenik.com เกี่ยว
กับรายการบทความที่มีคนเปิดเข้าดูในวันหนึ่งๆ โดยจะใช้เป็นรายการข้อมูล random มาแสดง
โดยในฝั่ง service api เราจะให้แนวทางเบื้องต้นอย่างง่ายสำหรับนำข้อมูลแสดงดังนี้
รูปแบบโครงสร้าง JSON Data ที่เราต้องการ จะเป็นดังนี้
[ { "id": "", "topic": "", "description": "", "date": "", "img": "", "view": "" }, { "id": "", "topic": "", "description": "", "date": "", "img": "", "view": "" } ]
จะเป็น array ของ object ในรูปแบบ json data string
สมมติตารางข้อมูลของเราชื่อ "table" มีฟิลด์ต่างๆ ตามรูปแบบของ property ข้อมูลตามโครงสร้าง json data
ด้านบน เราสามารถสร้าง service api ตามแนวทางดังนี้
ไฟล์ dbconnect.php
<?php $mysqli = new mysqli("localhost", "root","","test"); /* check connection */ if ($mysqli->connect_errno) { printf("Connect failed: %s\n", $mysqli->connect_error); exit(); } if(!$mysqli->set_charset("utf8")) { printf("Error loading character set utf8: %s\n", $mysqli->error); exit(); }
ไฟล์ api.php
<?php header('Access-Control-Allow-Origin: *'); header("Content-type:application/json; charset=UTF-8"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); require_once("dbconnect.php"); $json_data = array(); $more_sql=""; if(isset($_GET['id']) && $_GET['id']!=""){ $more_sql=" AND id='".$_GET['id']."' "; } $sql = " SELECT id,topic,description,date,img,view FROM table WHERE 1 $more_sql ORDER BY id LIMIT 0,10 "; $result = $mysqli->query($sql); if($result && $result->num_rows > 0){ while($row = $result->fetch_assoc()){ $json_data[] = array( "id" => $row['id'], "topic" => $row['topic'], "description" => $row['description'], "date" => $row['date'], "img" => $row['img'], "view" => $row['geo_id'] ); } } // แปลง array เป็นรูปแบบ json string if(isset($json_data)){ $json= json_encode($json_data); if(isset($_GET['callback']) && $_GET['callback']!=""){ echo $_GET['callback']."(".$json.");"; }else{ echo $json; } } ?>
จากรูปแบบโค้ดด้านบน เราจะเห็นว่า service api อย่างง่ายของเรา รองรับการเรียกดูข้อมูลเฉพาะรายการ โดยใช้
การตรวจสอบว่า มีการส่งค่า id ของรายการที่ต้องการดูข้อมูลมาหรือไม่ ถ้ามีการส่งค่ามา ก็ใช้เป็นเงื่อนไขในการ
กำหนดการคิวรี่เพิ่มเติม
สร้าง Provider สำหรับดึงข้อมูล
ต่อไปเราจะทำการสร้าง provider สำหรับเป็น service ในการไปดึงข้อมูลจาก service api โดยในเราสร้างด้วย
ionic cli ดังนี้
ionic generate provider article-service
จะได้ไฟล์ article-service.ts ในโฟลเดอร์ providers > article-service ให้กำหนดการใช้งานดังนี้
ไฟล์ article-service.ts
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable() export class ArticleServiceProvider { public urlApi:string = "http://localhost/demo/api.php"; constructor( public http: HttpClient ) { // console.log('Hello ArticleServiceProvider Provider'); } getArticle(id?:any){ return this.http.get(this.urlApi,{ params: { id:id!=null?id:'' } }); } }
สำหรับใครที่ยังไม่เคยใช้งาน หรือยังไม่รู้จักวิธีการใช้งาน provider หรือ service ใน ionic สามารถกลับไปย้อน
ทบทวนได้ทีบทความ
การดึงข้อมูลจาก Service API ด้วย HttpClient ใน ionic เบื้องต้น http://niik.in/863
https://www.ninenik.com/content.php?arti_id=863 via @ninenik
ใช้งาน Popover สร้างเงื่อนไข การดึงข้อมูลด้วย Provider ใน ionic http://niik.in/864
https://www.ninenik.com/content.php?arti_id=864 via @ninenik
การใช้งาน Loading , Card และการส่งค่าระหว่าง Page
ตอนนี้เราได้ service api ฝั่ง server และ providers service ฝั่ง client สำหรับไปดุึงข้อมูลเรียบร้อยแล้ว
ต่อไป ก็จะเป็นส่วนของหน้าการแสดงข้อมูล และวิธีการแสดงข้อมูล
ตามที่ได้บอกไปข้างต้นแล้วว่า เราจะแสดงข้อมูลแบบ card โดยจะเป็นข้อมูล article บทความ รูปแบบก็คือ
เราจะมีหน้า page หลัก เป็นหน้าที่จะดึงรายการทั้งหมดมาแสดง โดยไม่มีการส่ง id ใดๆ เข้าไป ส่วนอีก page ก็จะ
เป็นหน้ารายละเอียด สำหรับใช้แสดงเนื้อหาเฉพาะรายการที่เรากดเลือกจากหน้าหลักและมีการส่ง id เข้าไปยัง
service api เพื่อดึงเฉพาะข้อมูลรายการที่มี id ตรงกัน ในที่นี้เราจะสร้าง page ขึ้นมา 2 อันคือ article และ
article detail ด้วย ionic cli ดังนี้
ionic generate page article --no-module
ionic generate page article-detail --no-module
เราได้โครงสร้างส่วนของไฟล์ page ที่เกี่ยวข้องมาตังนี้
ก่อนไปดูส่วนของโค้ด และรายละเอียดการทำงาน ขอให้ดูตัวอย่างผลลัพธ์ ตามลำดับดังนี้
เมื่อเราเข้ามายังหน้าหลักของ article เราจะมีการเรียกใช้งาน Loading component โดยก่อนที่ provider สำหรับ
ดึงข้อมูลจะทำงาน เราให้แสดง loading เพื่อให้ผู้ใช้รอข้อมูลสักครู่ ซึ่งการทำงานในส่วนนี้จะช้าหรือเร็วก็ขึ้นกับปัจจัย
ต่างๆ เช่น ความเร็วอินเทอร์เน็ต หรือปริมาณข้อมูลที่จะไปดึงมาแสดง บางครั้งอาจจะเห็น loading แป้บเดียว การที่เรา
กำหนดในส่วนนี้ ก็เพื่อในกรณีการดึงข้อมูลใช้เวลานานกว่าปกติ แทนที่ผู้ใช้จะเห็นหน้าโล่งขาว เปล่าๆ เราก็แสดงสถานะ
กำลังโหลดข้อมูลแทน โดยเมื่อได้ทำการดึงข้อมูลเรียบร้อยแล้ว ก็จะทำการปิดส่วนของ loading ไป และก็แสดงลิสราย
การข้อมูลในรุปแบบ card ดังรูปด้านบน ตามลำดับ
และเมื่อผู้ใช้เลือกดูรายการข้อมูลใดๆ เราก็จะส่งค่า id ของรายการข้อมูลนั้นไปยังหน้า รายละเอียด หรือก็คือหน้า page
อีกหน้า โดย id ที่ส่งไปยังหน้ารายละเอียด ก็จะถูกเรียกใช้งาน แล้วส่งไปยัง service เพื่อดึงข้อมูลอีกที รูปแบบการแสดง
ของหน้ารายละเอียดก็จะคล้ายๆ กับหน้าหลัก คือ แสดง loading ก่อน หากข้อมูลส่งกลับมาก็ปิดการแสดง loading และ
แสดงเนื้อหาของข้อมูล ตามรูปด้านบน ตามลำดับ
ต่อไปจะเป็นส่วนของโค้ด คำอธิบายบางส่วนแสดงในโค้ด เริ่มต้นที่ไฟล์แรก article.ts
ไฟล์ article.ts
import { Component } from '@angular/core'; import { NavController, NavParams, LoadingController } from 'ionic-angular'; // import page และ service มาใช้งาน import { ArticleServiceProvider } from '../../providers/article-service/article-service'; import { ArticleDetailPage } from '../article-detail/article-detail'; // สร้าง interface ของข้อมูลที่จะใช้กับ json data ที่ได้จากไปดึงค่าใน service api interface articles { id: number, topic: string, description: string, date: string, img: string, view: number } @Component({ selector: 'page-article', templateUrl: 'article.html', }) export class ArticlePage { public articleItems: articles; // สร้างตัวแปรสำหรับเก็บข้อมูล constructor( public navCtrl: NavController, public navParams: NavParams, public articleService: ArticleServiceProvider, // มีการใช้งาน provider service public loadingCtrl: LoadingController // มีการใช้งาน loading component ) { } ionViewDidLoad() { console.log('ionViewDidLoad ArticlePage'); // กำหนดรูปแบบของ loading ดูการปรับแต่งเพิ่มเติมได้ที่ // https://ionicframework.com/docs/api/components/loading/LoadingController/ let loading = this.loadingCtrl.create({ content: 'Loading ...' }); loading.present(); // แสดง loading // เรียกใช้งาน service this.articleService.getArticle() .subscribe((res: articles) => { console.log(res); this.articleItems = res; loading.dismiss(); // ปิด loading เมื่อดึงข้อมูลและกำหนดค่าให้ตัวแปรเรียบร้อยแล้ว }); } // ฟังก์ชั่นสำหรับเปิด page ใหม่ โดยมีการส่งค่า ไปใช้งาน openArticle(id: any) { this.navCtrl.push(ArticleDetailPage, { id: id }); } }
จากโค้ดข้างต้น เรามีการ import LoadingController เข้ามาเพิ่มเติมในบรรทัดที่ 2 และทำการ inject เพื่อใช้งานผ่านตัว
แปร loadingCtrl การปรับแต่งค่าเพิ่มเติมสามารถทำได้ เช่น เปลี่ยนรูป icon ตัว loading เป็นต้น สามารถดูการปรับแต่ง
เพิ่มเติมเกี่ยวกับ loading component ได้ที่
สำหรับคำสั่ง openArticle() นั้นเป็นฟังก์ชั่นที่เราสร้างเพื่อใช้สำหรับลิ้งค์ไปยังหน้ารายละเอียด มีการกำหนดให้รับค่า
parameter 1 ค่า เป็นค่า id โดยค่านี้เราจะส่งไปพร้อมกับการเปิดหน้า page รายละเอียดผ่านการเรียกใช้คำสั่ง
this.navCtrl.push(parameter1,parameter2)
- parameter1 เป็น page class ที่เราจะเปิดหรือแสดง
- parameter2 เป็น object ข้อมูลที่เราจะส่งไปใช้งานใน page ที่กำลังจะเปิด เรียกค่าส่วนนี้ว่า params
ต่อไปเป็นไฟล์แสดงรายการ article ทั้งหมด หรือก็คือไฟล์ article.html
ไฟล์ article.html
<ion-header> <ion-navbar color="primary"> <button ion-button menuToggle> <ion-icon name="menu"></ion-icon> </button> <ion-title>Article</ion-title> </ion-navbar> </ion-header> <ion-content> <ion-card (click)="openArticle(article.id)" *ngFor="let article of articleItems"> <ion-item> <h2>{{article.topic}}</h2> <ion-note>{{ article.date }}</ion-note> </ion-item> <img src="{{article.img}}"> <ion-card-content> {{article.description}} </ion-card-content> <ion-row> <ion-col> <button ion-button icon-left clear small> <ion-icon name="eye"></ion-icon> <div>{{article.view}} Views</div> </button> </ion-col> <ion-col> <button ion-button icon-left clear small> <ion-icon name="share"></ion-icon> <div>Share</div> </button> </ion-col> </ion-row> </ion-card> </ion-content>
รายละเอียดคงไม่ต้องอธิบายเท่าไหร่ เพราะเป็นรูปแบบการนำค่าข้อมูลมาแสดงที่ผ่านตามากันพอสมควรแล้ว รูปแบบที่ใช้
คือการแสดงข้อมูลแบบ card สามารถปรับแต่งหรือดูรูปแบบเพิ่มเติมได้ที่ลิ้งค์
หน้าตาผลลัพธ์การแสดงข้อมูลหน้า article ที่เป็นรายการข้อมูลทั้งหมด 10 รายการ ในรูปจะเห็นบางส่วนเท่านั้น
ต่อด้วยส่วนของไฟล์ดึงข้อมูลหน้ารายละเอียด ไฟล์ article-detail.ts คำอธิบายบางส่วนแสดงในโค้ด
ไฟล์ article-detail.ts
import { Component } from '@angular/core'; import { NavController, NavParams, LoadingController } from 'ionic-angular'; import { ArticleServiceProvider } from '../../providers/article-service/article-service'; interface articles{ id:number, topic:string, description:string, date:string, img:string, view:number } @Component({ selector: 'page-article-detail', templateUrl: 'article-detail.html', }) export class ArticleDetailPage { public article:articles; constructor( public navCtrl: NavController, public navParams: NavParams, public articleService:ArticleServiceProvider, public loadingCtrl: LoadingController ){ } ionViewDidLoad() { console.log('ionViewDidLoad ArticleDetailPage'); // ส่วนของการกำหนด loading let loading = this.loadingCtrl.create({ content: 'Loading ...' }); loading.present(); // แสดง loading // ส่วนของการดึงค่า params ที่ส่งมาจากหน้าหลักมาใช้งาน let id = this.navParams.get("id"); // เรียกใช้งาน provider service คราวนี้ส่ง id ของข้อมูลที่ต้องการแสดง this.articleService.getArticle(id) .subscribe((res:articles) =>{ console.log(res); this.article = res[0]; // เนื่องจากเป็นข้อมูลเดียว เราจึงอ้างอิงที่ array key = 0 ที่เป็นค่าแรก loading.dismiss(); // ปิด loading }); } }
จะเห็นว่าส่วนของการแสดงรายละเอียด จะคล้ายๆ กับหน้ารายการหลัก ที่มีเพิ่มเข้ามาก็คือการใช้ค่า params ที่ถูกส่ง
จาก page หลัก ผ่านการใช้งานคำสั่ง this.navParams.get('ชื่อ params ที่ส่งมา')
ส่วนสุดท้าย เป็นหน้าแสดงรายละเอียดของข้อมูลหลังจากเรียกใช้ service ไปดึงข้อมูลมาแล้ว ในที่นี้ เราจะใช้รูปแบบ
เดิม คือเป็น card เป็นแนวทางเท่านั้น
ไฟล์ article-detail.html
<ion-header> <ion-navbar color="dark"> <button ion-button menuToggle> <ion-icon name="menu"></ion-icon> </button> <ion-title>Article Detail</ion-title> </ion-navbar> </ion-header> <ion-content> <ion-card *ngIf="article"> <ion-item> <h2>{{article.topic}}</h2> <ion-note>{{ article.date }}</ion-note> </ion-item> <img src="{{article.img}}"> <ion-card-content> {{article.description}} </ion-card-content> <ion-row> <ion-col> <button ion-button icon-left clear small> <ion-icon name="eye"></ion-icon> <div>{{article.view}} Views</div> </button> </ion-col> <ion-col> <button ion-button icon-left clear small> <ion-icon name="share"></ion-icon> <div>Share</div> </button> </ion-col> </ion-row> </ion-card> </ion-content>
สิ่งที่ต่างออกไป คือเนื่องจากเราทำการดึงข้อมูล array ที่ key เท่ากับ 0 ตามโค้ดในไฟล์ article-detail.ts
ดังนั้นตัวแปร article จะเป็น object ไม่ได้เป็น array วิธีการแสดง เราจะใช้ ngIf แทน ngFor โดย ngIf ก็หมายถึง
ว่า ถ้ามีข้อมูล ก็ให้แสดง card โดยเชื่อมโยงข้อมูลผ่านตัวแปร article
หน้าตาผลลัพธ์การแสดงข้อมูลหน้า article detail จะแสดงรายละเอียดเพียงข้อมูลเดียว โดยเป็นรายการข้อมูลที่มี
id ตรงกับค่าที่ส่งมาจากหน้าหลัก เท่านั้น
เนื้อหาในตอนนี้ เราได้รู้จักการใช้งาน loading component การใช้ card component และการส่งค่าระหว่าง page ผ่าน
การกำหนด params เนื่องจากเนื้อหานี้ ไม่ค่อยมีอะไรที่ซับซ้อนมากนัก แต่ก็เป็นเนื้อหาที่เป็นพื้นฐานในการใช้งานทั่วไป
ที่มักพบเห็นบ่อย เช่น การแสดงข่าวสาร การแสดงโปรโมชั่น การแสดงกิจกรรมหรือบทความ ก็จะมีรุปแบบคล้ายๆ กับการ
ใช้งานข้างต้น ในการอธิบายการใช้งาน ผู้เขียนตัดทอนหลายๆ ส่วน ซึ่งได้เคยกล่าวไปแล้วในบทความผ่านๆ มา ทั้งนี้ก็เพื่อให้
เนื้อหากระชับ หากใครเพื่งมาอ่านหรือเพิ่งติดตาม ก็อาจจะต้องกลับไปไล่ดูย้อนเนื้อหาก่อนๆ ประกอบ
เนื้อหาตอนหน้าจะเป็นเกี่ยวกับอะไร โปรดรอติดตาม