0

I'm working on angular project and creating pagination from JSON Object like Example.

If I put dummy JSON Array of Objects from .ts file as shown in above example my code works fine. But when I get same Array of Objects from an HTTP request it shows me below error in my browser console.

enter image description here

I think JSON Array of Objects not properly mapped with my Array of Object type Posts.

Here is my code app.component.ts:

import {
  Component,
  OnInit
} from '@angular/core';
import * as _ from 'underscore';
import {
  Http,
  Headers,
  RequestOptions,
  Response
} from '@angular/http';
import {
  Observable
} from 'rxjs/Observable';
import 'rxjs/add/operator/map'
import {
  post
} from 'selenium-webdriver/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  pagerService: PagerService = new PagerService();
  columns: string[];
  posts: any[];
  getFilteredData: Object;
  pagedItems: any[];
  rows: number;
  count: number;

  // pager object
  pager: any = {};

  ngOnInit() {
    this.columns = ['userId', 'id', 'title', 'body'];
    this.count = this.columns.length;
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(json => {
        this.posts = json;
      })
    this.getFilteredData = this.posts;
    this.rows = 100;
    // initialize to page 1
    this.setPage(1);
  }


  constructor(private http: Http) {


  }

  onSearching(searchValue: string) {
    this.getFilteredData = this.posts.filter((d: Posts) => {
      return d.title.toLowerCase().includes(searchValue.toLowerCase())
    });
    this.rows = this.getFilteredData.length;
  }

  setPage(page: number) {
    if (page < 1 || page > this.pager.totalPages) {
      return;
    }

    // get pager object from service
    this.pager = this.pagerService.getPager(this.rows, page);

    // get current page of items
    this.pagedItems = this.getFilteredData.slice(this.pager.startIndex, this.pager.endIndex + 1);
  }
}

class Posts {
  userId: number;
  id: number;
  title: string;
  body: string;
  constructor() {

  }
}

class PagerService {
  getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
    // calculate total pages
    let totalPages = Math.ceil(totalItems / pageSize);

    let startPage: number, endPage: number;
    if (totalPages <= 10) {
      // less than 10 total pages so show all
      startPage = 1;
      endPage = totalPages;
    } else {
      // more than 10 total pages so calculate start and end pages
      if (currentPage <= 6) {
        startPage = 1;
        endPage = 10;
      } else if (currentPage + 4 >= totalPages) {
        startPage = totalPages - 9;
        endPage = totalPages;
      } else {
        startPage = currentPage - 5;
        endPage = currentPage + 4;
      }
    }

    // calculate start and end item indexes
    let startIndex = (currentPage - 1) * pageSize;
    let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);

    // create an array of pages to ng-repeat in the pager control
    let pages = _.range(startPage, endPage + 1);

    // return object with all pager properties required by the view
    return {
      totalItems: totalItems,
      currentPage: currentPage,
      pageSize: pageSize,
      totalPages: totalPages,
      startPage: startPage,
      endPage: endPage,
      startIndex: startIndex,
      endIndex: endIndex,
      pages: pages
    };
  }
}

When I replace this line of code:

fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(json => {
        this.posts = json;
      })

with below dummy data:

this.posts = [
      {
        userId: 1,
        id: 1,
        title: 'Loreum ispum',
        body: 'dummy text' 
      },
      {
        userId: 1,
        id: 1,
        title: 'Loreum ispum',
        body: 'dummy text' 
      },
      {
        userId: 1,
        id: 1,
        title: 'Loreum ispum',
        body: 'dummy text' 
      },
      {
        userId: 1,
        id: 1,
        title: 'Loreum ispum',
        body: 'dummy text' 
      }
    ];

every thing works fine. Here is an Output:

enter image description here

and here is the working example of this link:

enter image description here

Please help me on this what I'm doing wrong.

Ahmer Ali Ahsan
  • 5,636
  • 16
  • 44
  • 81
  • 3
    The value of `this.posts` is `undefined` when you assign it to `this.getFilteredData`. `fetch` is **asynchronous**. Have a look at [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/q/23667086/218196) to learn more about async code. – Felix Kling Apr 26 '18 at 22:44
  • Can you try: ```if (this.getFilteredData) { this.pagedItems = this.getFilteredData.slice(this.pager.startIndex, this.pager.endIndex + 1); }``` – cassmtnr Apr 26 '18 at 22:58

2 Answers2

1

Try by doing the slice into the fetch callback.

fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(json => {
        this.posts = json;
        //input your code here     
        this.getFilteredData = this.posts;        
        this.pagedItems = this.getFilteredData.slice(this.pager.startIndex, this.pager.endIndex + 1);    
      })
Abel Valdez
  • 2,368
  • 1
  • 16
  • 33
  • By using above code I get the data. But error not resolve still showing `ERROR TypeError: Cannot read property 'slice' of undefined` and this error coming from in this `setPage()` method I've calling `this.pagedItems = this.getFilteredData.slice(this.pager.startIndex, this.pager.endIndex + 1);` – Ahmer Ali Ahsan Apr 27 '18 at 05:15
  • The main problem is, when you are trying to call `setPage()` function your `this.getFilteredData` is undefined that's mean that the request from fetch isn't finished because is an async function. a posible solution for your code logic, is by using a **promise** instead of **fetch**. – Abel Valdez Apr 27 '18 at 14:45
1

Move setPage function also to the service success function so that posts, getFliteredData will be available at the time of slicing.

fetch('https://jsonplaceholder.typicode.com/posts')
  .then(response => response.json())
  .then(json => {
    this.posts = json;      
    this.getFilteredData = this.posts;
    this.rows = 100;
    this.setPage(1);  
  }).
Lakshmi Prasanna
  • 440
  • 4
  • 16