Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Pagination Angular2 with Django Rest Framework API

I am trying to create a simple blog application using Angular2 with Django Rest Framework. I am implementing pagination in Django, but I do not know how to rendering it in Angular.

API has the following structure. Entries are paginated every 5 entries.

enter image description here


ng2app/src/app/models/entries.model.ts

export interface IEntries {
  count: any,
  next: any,
  previous: any,
  results: IResults[]
}

export interface IResults {
  title: string,
  body: string,
  created_at: any,
  updated_at: any
}


ng2app/src/app/services/entries.service.ts

import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import 'rxjs/add/operator/toPromise';

import { IEntries } from '../models/entries.model';

@Injectable()
export class EntriesService {

  constructor(
    private http: Http
  ){
  }

  getEntries(page: number){
    return this.http
      .get(`http://127.0.0.1:8000/api/entries/?limit=5&offset=` +((page * 5)-5))
      .toPromise()
      .then(response => response.json())
      .catch(this.handleError);
  }

  private handleError(error: any) {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }

}


ng2app/src/app/services/entries.component.ts

import { Component, OnInit } from '@angular/core';
import { EntriesService } from '../services/entries.service';
import { IEntries } from '../models/entries.model';


@Component({
  selector: 'my-entries',
  templateUrl: '../templates/entries.component.html',
  styleUrls: ['../static/entries.component.css']
})
export class EntriesComponent implements OnInit{
  title = 'entries';
  entries: IEntries[] = [];
  error: any;

  public constructor(
    private entriesService: EntriesService,
  ){}

  getEntires(page :number) {
    this.entriesService
      .getEntries(page)
      .then(entries => this.entries = entries)
      .catch(error => this.error = error);
  }

  ngOnInit() {
    this.getEntires(1);
  }
}


ng2app/src/app/templates/entries.component.html

<div class="container">
  <h2>{{title}}</h2>
  <div class="panel panel-default" *ngFor="let results of entries.results">
    <div class="panel-heading"><a href="detail/{{ results.id }}">{{ results.title }}</a></div>
    <div class="panel-body pre-wrap" ng-bind="multiLineText">{{ results.body }}</div>
    <div class="panel-footer">{{ results.created_at | date}}</div>
  </div>
  <nav *ngIf="entries.count > 5">
      (I want to display pagination here)
  </nav>
</div>


In such a case, please help how to implement Pagination.

like image 732
xKxAxKx Avatar asked Apr 15 '17 10:04

xKxAxKx


1 Answers

After implementing pagination in the Django backend, querying the backend would return results in the following format:

"data": {
   "count": ,
   "next": "",
   "previous": "",
   "results": []
}

count: The total number of items returned.

next: The URL to the next items after performing pagination

previous: The URL to the previous items after you have navigated to the next. set of items

results: The items requested for from the backend, paginated obviously i.e if pagination was set to 10 items and 15 were returned, results would return 10 items on the first request, then after navigating to the URL in next, results would return the remaining 5.

Service

@Injectable({
  providedIn: "root"
})
export class OurService {  
  constructor(private http: HttpClient) {}

  // Here,we make our request to the backend API, this observer takes in the backend
  // api url as a parameter and performs a GET request
  getAllTransactions(APIUrl: string): Observable<any> {
    return this.http.get<>(APIUrl);
  }
}

Component

@Component({
  selector: "app-transactions",
  templateUrl: "./transactions.component.html",
  styleUrls: ["./transactions.component.scss"]
})
export class TransactionsComponent implements OnInit {
  transactions: Transacton[];
  transactionsUrl = "http://.../api/v1/transactions/"; //url to query for the transactions
  next: string;
  previous: string;

  constructor(private transactionService: TransactionService) {}

  ngOnInit(): void {
    // On component initialization, load the transactions on the page
    this.getTransactions(this.transactionsUrl);
  }

  getTransactions(url: string) {
    this.transactionService.getAllTransactions(url).subscribe(res => {
      this.transactions = res.data.results;
      if (res.data.next) {
        // set the components next transactions here from the response
        this.next = res.data.next;
      }

      if (res.data.previous) {
        // set the components previous transactions here from the response
        this.previous = res.data.previous;
      }
    });
  }

  // function fetches the next paginated items by using the url in the next transactions
  fetchNext() {
    this.getTransactions(this.next);
  }

  // function fetches the previous paginated items by using the url in the previous transactions
  fetchPrevious() {
    this.getTransactions(this.previous);
  }

HTML

<div class="page-buttons">
  <button class="btn prev" (click)="fetchPrevious()">
  </button>
  <button class="btn next" (click)="fetchNext()">
  </button>
</div>
like image 60
Philip Mutua Avatar answered Oct 04 '22 17:10

Philip Mutua