Ionic 3 i WordPress REST API - prikaz blog postova

Ionic 3 i WordPress REST API – prikaz blog postova

U ovom ću blog postu napraviti primjer Ionic 3 aplikacije koja će prikazivati popis blog postova sa ovog bloga koristeći WordPress REST API.

Na početnoj stranici biti će popis blog postova (naziv, vrijeme objave, kategorije, kratak sadržaj i slika) te će se moći pristupiti svakom blog postu pojedinačno.

Kreiranje aplikacije

Za početak kreiram novu Ionic aplikaciju i odmah dodajem Android platformu kako bi kasnije mogao aplikaciju pokrenuti na Android mobilnom uređaju.

$ ionic start Ionic3WordPressBlog blank
$ cd Ionic3WordPressBlog 
$ ionic cordova platform add android

API provider

Sada ću kreirati API Provider koji će služiti kao centralno mjesto svih WordPress URL-ova koje ću koristiti unutar Ionic aplikacije.

$ ionic g provider ApiProvider

Na URL-u https://www.tomislavstankovic.com/blog/wp-json/wp/v2/posts dohvaćam popis blog postova. Unutar ovog API-ja također imam dva vrlo bitna podatka, a to su featured_media i categories koji će mi poslužiti za dohvaćanje slike i kategorije svakog blog posta.

Ionic 3 i WordPress REST API - prikaz blog postova

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';

@Injectable()
export class ApiProvider {

  osnovniUrl: string = "https://www.tomislavstankovic.com/blog/wp-json/wp/v2/";

  constructor(public _http: HttpClient) {
    console.log('Hello ApiProvider Provider');
  }

  blogPostovi(){
    return this._http.get(this.osnovniUrl + 'posts')
    .map(data => Object.keys(data).map(k => data[k]))
  }

  slikaBlogPosta(a:any){
    return this._http.get(this.osnovniUrl + 'media' + a)
    .map(data => Object.keys(data).map(k => data[k]))
  }

  kategorijaBlogPosta(){
    return this._http.get(this.osnovniUrl + 'categories/?per_page=100')
    .map(data => Object.keys(data).map(k => data[k]))
  }

}

Prikaz blog postova

Aplikacija će na kraju izgledati ovako:

Ionic 3 i WordPress REST API – prikaz blog postova

Kao što se može vidjeti na početnom ekranu nalazi se popis zadnjih 10 blog postova. Svaki blog post ima naslov, sliku, kratak sadržaj i vrijeme proteklo od objave. Nekoliko preduvjeta je bilo potrebno zadovoljiti kako bi se sve to prikazalo na taj način.

Struktura početne stranice izgleda ovako i ovdje je posebno zanimljiva funkcija prikaziJedanBlogPost() pomoću koje prosljeđujem potrebne podatke na stranicu za prikaz pojedinačnog blog posta.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic3WordPress
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
 
  <ion-card *ngFor="let post of jedanBlogPost; let i = index" tappable>
    <div *ngFor="let slika of jednaSlika; let i = index" (click)="prikaziJedanBlogPost({id:post.id, naslov:post.naslov, sadrzaj: post.sadrzaj, urlslike: slika.putanjaSlike, index: i})">
        <div *ngIf="post.id == slika.idBlogPosta">
         <img [src]="slika.putanjaSlike">
         <span class="vrijeme"><ion-icon name="time"></ion-icon> {{ post.vrijeme }}</span>
         <span class="kategorija"><ion-icon name="ios-bookmark-outline"></ion-icon> {{post.kategorije | KategorijaPipe:kategorije}}</span>
        </div>
      </div>
      <ion-card-content (click)="prikaziJedanBlogPost({id:post.id, naslov:post.naslov, sadrzaj: post.sadrzaj, urlslike: slika.putanjaSlike, index: i})">
          <ion-card-title [innerHTML]="post.naslov">
          </ion-card-title>
          <div [innerHTML]="post.uvod"></div>
        </ion-card-content>
</ion-card>

</ion-content>

Još jedna zanimljiva stvar u home.html je KategorijaPipe koja služi za dohvaćanje naziva kategorije na osnovu ID-a.

$ ionic generate pipe KategorijaPipe
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'KategorijaPipe',
})
export class KategorijaPipe {

  transform(value, args) {
    let output = '';
    value.forEach(function(number){
      output = output + ' ' + args[number]
    })
    return output;
  }
}

Naravno, potrebno je još o svemu tome obavijestiti app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { ApiProvider } from '../providers/api/api';

import { HttpClientModule } from '@angular/common/http'; 
import { KategorijaPipe } from '../pipes/kategorija/kategorija';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    KategorijaPipe
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    HttpClientModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    ApiProvider
  ]
})
export class AppModule {}

Uz nešto malo CSS-a

page-home {

    .vrijeme {
        position: relative;
        color: #fff;
        background-color: #3F9FCF;
        padding: 1px;
    }

    .toolbar-background {
        background-color: #3F9FCF;
    }

    .toolbar-title {
        color: #fff;
    }

    .kategorija {
        position: absolute;
        right: 10px;
        background-color: #3F9FCF;
        color: #fff;
        padding: 1px;
    }

}

Kao što se može vidjeti u home.ts za prikaz vremena u željenom obliku koristio sam Moment.js

Pojašnjenje funkcija:

  • prikazBlogPostova() – dohvaća popis blog postova i kreira niz (array) jedanBlogPost
  • dohvatiUrlSlike() – dohvaća URL slike pojedinačnog blog posta na osnovu parametra idslike: res[i].featured_media iz gornje funkcije
  • ucitajKategorije() – dohvaća kategorije za blog post
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ApiProvider } from './../../providers/api/api';

import moment from 'moment';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
  providers: [ApiProvider]
})
export class HomePage {

  jedanBlogPost: Array<Object>;
  jednaSlika: Array<Object>;
  putanjaSlike: any;
  kategorije: any;

  constructor(public _navCtrl: NavController,
              public _api: ApiProvider) {
  }

  ionViewDidLoad(){
    moment.locale('hr');
    this.prikazBlogPostova();
    this.ucitajKategorije();
  }

  prikazBlogPostova(){
    this.jedanBlogPost = [];
    this.jednaSlika = [];
    this._api.blogPostovi().subscribe(res => {
      for(var i = 0; i < res.length; i++) {
        //Funkcija koja dohvaća sliku - početak
        this.dohvatiUrlSlike(res[i].featured_media);
        //Funkcija koja dohvaća sliku - kraj
        this.jedanBlogPost.push({id: res[i].id,
                             naslov: res[i].title.rendered,
                             uvod: res[i].excerpt.rendered,
                             sadrzaj: res[i].content.rendered,
                             kategorije: res[i].categories,
                             vrijeme: moment.utc(res[i].modified_gmt).fromNow(),
                             idslike: res[i].featured_media}); 
       }

    });
  }

  dohvatiUrlSlike(a){
    this.putanjaSlike = {};
    this._api.slikaBlogPosta(a).subscribe(res => {
      this.jednaSlika.push({
               idSlike: res[0],
               idBlogPosta: res[22],
               putanjaSlike: res[23]});
      }); 
  }

  ucitajKategorije(){
    let categoryArray = [];
    this._api.kategorijaBlogPosta().subscribe(res => {
      res.forEach(function(item){
        categoryArray[item.id] = item.name;
      })
      this.kategorije = categoryArray;
    }); 
  } 

  prikaziJedanBlogPost(a){
    this._navCtrl.push('JedanBlogPostPage', a);
  }

}

Klikom na naslov ili sliku blog posta otvara se jedan blog post. Stranica jednog blog posta kreirana je sljedećom naredbom

$ ionic generate page JedanBlogPost

Dok je struktura ovakva

<ion-header>
  <ion-navbar color="secondary">
    <ion-title [innerHTML]="naslov"></ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
    <img [src]="slika">
  <ion-card>
    <ion-card-content>
        <div [innerHTML]="sadrzaj"></div>
    </ion-card-content>
  </ion-card>
</ion-content>

Funkcionalnost stranice za prikaz jednog blog posta ne radi ništa osim dohvaćanja proslijeđenih podataka s prethodne stranice s popisom svih blog postova pomoću objekta NavParams.

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-jedan-blog-post',
  templateUrl: 'jedan-blog-post.html'
})
export class JedanBlogPostPage {

  naslov:any;
  sadrzaj:any;
  slika:any;

  constructor(public _navCtrl: NavController, 
              public _navParams: NavParams) {
  }

  ionViewWillEnter() {
    this.naslov = this._navParams.data.naslov;
    this.sadrzaj = this._navParams.data.sadrzaj;
    this.slika = this._navParams.data.urlslike;
  }

}

Zaključak

Struktura projekta prema package.json izgleda ovako

{
  "name": "Ionic3WordPressBlog",
  "version": "0.0.1",
  "author": "Tomislav Stanković",
  "homepage": "https://www.tomislavstankovic.com/",
  "private": true,
  "scripts": {
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "lint": "ionic-app-scripts lint",
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  },
  "dependencies": {
    "@angular/common": "5.0.3",
    "@angular/compiler": "5.0.3",
    "@angular/compiler-cli": "5.0.3",
    "@angular/core": "5.0.3",
    "@angular/forms": "5.0.3",
    "@angular/http": "5.0.3",
    "@angular/platform-browser": "5.0.3",
    "@angular/platform-browser-dynamic": "5.0.3",
    "@ionic-native/core": "4.4.0",
    "@ionic-native/splash-screen": "4.4.0",
    "@ionic-native/status-bar": "4.4.0",
    "@ionic/storage": "2.1.3",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "moment": "^2.21.0",
    "rxjs": "5.5.2",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.18"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.1.8",
    "typescript": "2.4.2"
  },
  "description": "Ionic3WordPressBlog"
}

Objavio

Tomislav Stanković

Bloger širokog raspona interesa od kojih dio voli objaviti na ovom blogu. U neslobodno vrijeme Angular developer mobilnih i web aplikacija.

Odgovori

Vaša adresa e-pošte neće biti objavljena. Obavezna polja su označena sa *