分页在 api 系统中如何工作(前端是 angular2,后端是 laravel5.4)?

How pagination works in api system (frontend is angular2 and backend is laravel5.4)?

我有一个酒店预订项目,前端是使用 angular2 创建的,后端是使用 laravel 创建的,它是一个 API 系统。我在 angular2 中有一个 table 列表。为此,我从 laravel 获取了预订数据并在 angular table 中绑定,但我不知道 api 中的分页是如何工作的。最初我只获取并绑定了 15 个数据。当我们点击下一页时如何访问更多数据。这是 laravel angular.

的代码

Laravel

public function index()
{
   $bookings = Booking::where('is_delete', 0)
            ->paginate(15);

   return response()->json(['bookingDetails' => $bookings], 200);
}

角度2

booking.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';

import { Bookings } from './booking';

import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
import { Observable } from "rxjs";

@Injectable()
export class BookingService {
    private headers = new Headers({'Content-Type': 'application/json'});
    private _url: string = 'http://cabinapi.app/api/bookings/';
    /*private _url: string = 'apidata/testData.json';*/
    constructor(private http: Http) { }

    getBooking(): Observable<any> {
        return this.http.get(this._url)
            .map((response: Response) => response.json().bookingDetails.data as Bookings[])
            .catch(this.handleError);
    }
    private handleError(error: any): Promise<any> {
        console.error('An error occurred', error); // for demo purposes only
        return Promise.reject(error.message || error);
    }
}

booking.component.ts

import { Component, OnInit } from '@angular/core';

import { BookingService } from './booking.service';
import { Bookings } from './booking';
@Component({
    selector: 'booking',
    templateUrl: './booking.component.html'
})
export class BookingComponent implements OnInit {
    bookings: Bookings[];
    constructor(private employeeService: BookingService) {}
    getBooking(): void {
        /*this.employeeService.getEmployee().then(employees => this.employees = employees);*/
        this.employeeService.getBooking().subscribe(bookings => this.bookings = bookings);
    }
    ngOnInit(): void {
        this.getBooking();
        setTimeout(function () {
            $(function() {
                $("#dataTable").DataTable();
            });
        }, 1000);
    }
}

Laravel 分页器结果 类 实现了 Illuminate\Contracts\Support\Jsonable 接口契约并公开了 toJson 方法,因此很容易将您的分页结果转换为 JSON, 您可以简单地从控制器 return

public function index()
{
   $bookings = Booking::where('is_delete', 0)
            ->paginate(15);

   return $bookings;
}

结果应该是这样的

{
   "total": 50,
   "per_page": 15,
   "current_page": 1,
   "last_page": 4,
   "next_page_url": "http://example.app?page=2",
   "prev_page_url": null,
   "from": 1,
   "to": 15,
   "data":[
        {
            // Result Object
        },
        {
            // Result Object
        }
   ]
}

您只需在前端实现分页流程即可。

以下是构建可与本机 Laravel 分页系统一起使用的分页 Angular UI 的方法:

首先,为了帮助,创建一个 BookingPaginatedBooking class(我的预订很简单,只有描述 -- 根据需要自定义):

booking.model.ts:

export class Booking {
  id: number;
  description: string;
}

分页-booking.model.ts表示Laravel

返回的分页数据
import { Booking } from './booking.model'

export class PaginatedBooking {
  current_page: number;
  data: Booking[];
  from: number;
  last_page: number;
  next_page_url: string;
  path: string;
  per_page: number;
  prev_page_url: string;
  to: number;
  total: number;
}

然后创建您的服务以获取分页预订数据。添加一个 getBookingsAtUrl(url) 函数——稍后我们将使用它在您点击 prev/next 按钮时从 Laravel 请求特定的分页数据集:

booking.service.ts

export class BookingService {
    private bookingUrl: string = '/api/bookings'
    constructor(private http: Http) { }

    getBookings(): Promise<PaginatedBooking>{
        return this.http.get(this.bookingUrl)
        .toPromise()
        .then(response => response.json() as PaginatedBooking)
        .catch(this.handleError);
    }

    getBookingsAtUrl(url: string): Promise<PaginatedBooking>{
        return this.http.get(url)
        .toPromise()
        .then(response => response.json() as PaginatedBooking)
        .catch(this.handleError);
    }

    private handleError(error: any): Promise<any> {
        console.error('An error occurred', error); // for demo purposes only
        return Promise.reject(error.message || error);
    }
}

在您的组件中,实施 ngOnInit() 以获取您的初始预订数据。然后实现一个 getPrev() 函数和一个 nextPage() 函数,当这些按钮被点击时调用 Bookings 服务:

booking.component.ts:

export class BookingComponent implements OnInit {
  bookings:PaginatedBooking;
  constructor(private service: NativeBookingService) { }

  ngOnInit() {
    this.service.getBookings().then(bookings=>this.bookings = bookings);
  }

  prevPage() {
    this.service.getBookingsAtUrl(this.bookings.prev_page_url).then(bookings=>this.bookings = bookings);
  }

  nextPage() {
    this.service.getBookingsAtUrl(this.bookings.next_page_url).then(bookings=>this.bookings = bookings);
  }
}

最后,您的组件模板:

booking.component.html:

<div *ngIf="bookings">
  <ul>
    <li *ngFor="let booking of bookings.data">{{booking.description}}</li>
  </ul>
  <p>Showing booking {{bookings.from}} to {{bookings.to}} of {{bookings.total}}</p>
  <p>Page {{bookings.current_page}} of {{bookings.last_page}}</p>
  <button (click)="prevPage()" [disabled]="!bookings.prev_page_url" >Prev</button>
  <button (click)="nextPage()" [disabled]="!bookings.next_page_url">Next</button> 
</div>

应该就可以了。为简洁起见,我省略了一些导入。根据需要自定义您的模板。 我这里有一个示例项目演示了它们是如何组合在一起的,但请注意我的 Angular 文件的命名略有不同,我添加了一个简单的加载状态:

https://github.com/SpaceFozzy/laravel-angular-pagination

你可以see the live demo here.

祝你好运!