All Projects โ†’ nodes-vapor โ†’ paginator

nodes-vapor / paginator

Licence: MIT license
Offset pagination for Vapor ๐Ÿ—‚

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to paginator

auth
๐Ÿ‘ค Authentication and Authorization framework for Fluent.
Stars: โœญ 51 (-23.88%)
Mutual labels:  vapor, server-side-swift, fluent
fluent-mysql-driver
๐Ÿ–‹๐Ÿฌ Swift ORM (queries, models, relations, etc) built on MySQL.
Stars: โœญ 69 (+2.99%)
Mutual labels:  vapor, server-side-swift, fluent
fluent-postgres-driver
๐Ÿ˜ PostgreSQL driver for Fluent.
Stars: โœญ 120 (+79.1%)
Mutual labels:  vapor, server-side-swift, fluent
flash
Flash messages between views โšก๏ธ
Stars: โœญ 34 (-49.25%)
Mutual labels:  vapor, server-side-swift, vapor-2
bugsnag
Report errors with Bugsnag ๐Ÿ›
Stars: โœญ 37 (-44.78%)
Mutual labels:  vapor, server-side-swift, vapor-2
template
A Vapor template for convenient and fast scaffolding ๐ŸŽ
Stars: โœญ 33 (-50.75%)
Mutual labels:  vapor, server-side-swift, vapor-2
sourcery-templates
Building Vapor projects using meta programming with Sourcery โœจ
Stars: โœญ 24 (-64.18%)
Mutual labels:  vapor, server-side-swift, vapor-2
Fluent Sqlite Driver
Fluent driver for SQLite
Stars: โœญ 51 (-23.88%)
Mutual labels:  vapor, server-side-swift, fluent
Vapor Oauth
OAuth2 Provider Library for Vapor
Stars: โœญ 90 (+34.33%)
Mutual labels:  vapor, server-side-swift
Vaporsecurityheaders
Harden Your Security Headers For Vapor
Stars: โœญ 107 (+59.7%)
Mutual labels:  vapor, server-side-swift
sqlite-kit
Non-blocking SQLite client library with SQL builder built on SwiftNIO
Stars: โœญ 51 (-23.88%)
Mutual labels:  vapor, server-side-swift
Fluent Kit
Swift ORM (queries, models, and relations) for NoSQL and SQL databases
Stars: โœญ 82 (+22.39%)
Mutual labels:  vapor, fluent
Vapor Clean
A Vapor 3 template with no additional cruft.
Stars: โœญ 80 (+19.4%)
Mutual labels:  vapor, server-side-swift
Sql Kit
*๏ธโƒฃ Build SQL queries in Swift. Extensible, protocol-based design that supports DQL, DML, and DDL.
Stars: โœญ 115 (+71.64%)
Mutual labels:  vapor, server-side-swift
Aws
Swift wrapper around AWS API
Stars: โœญ 67 (+0%)
Mutual labels:  vapor, server-side-swift
Flock
Automated deployment of Swift projects to servers
Stars: โœญ 127 (+89.55%)
Mutual labels:  vapor, server-side-swift
Mistkit
Swift Package for Server-Side and Command-Line Access to CloudKit Web Services
Stars: โœญ 129 (+92.54%)
Mutual labels:  vapor, server-side-swift
Core
๐ŸŒŽ Utility package containing tools for byte manipulation, Codable, OS APIs, and debugging.
Stars: โœญ 62 (-7.46%)
Mutual labels:  vapor, server-side-swift
Open Crypto
๐Ÿ”‘ Hashing (BCrypt, SHA2, HMAC), encryption (AES), public-key (RSA), and random data generation.
Stars: โœญ 115 (+71.64%)
Mutual labels:  vapor, server-side-swift
Api Template
๐Ÿ’ง A starting point for Vapor APIs.
Stars: โœญ 130 (+94.03%)
Mutual labels:  vapor, server-side-swift

Paginator ๐Ÿ—‚

Swift Version Vapor Version Circle CI codebeat badge codecov Readme Score GitHub license

GIF of paginator

This package currently offers support for offset pagination on Array and QueryBuilder.

๐Ÿ“ฆ Installation

Add Paginator to the package dependencies (in your Package.swift file):

dependencies: [
    ...,
    .package(url: "https://github.com/nodes-vapor/paginator.git", from: "4.0.0")
]

as well as to your target (e.g. "App"):

targets: [
    ...
    .target(
        name: "App",
        dependencies: [... "Paginator" ...]
    ),
    ...
]

Next, copy/paste the Resources/Views/Paginator folder into your project in order to be able to use the provided Leaf tags. These files can be changed as explained in the Leaf Tags section, however it's recommended to copy this folder to your project anyway. This makes it easier for you to keep track of updates and your project will work if you decide later on to not use your own customized leaf files.

Getting started ๐Ÿš€

First make sure that you've imported Paginator everywhere it's needed:

import Paginator

Adding the Leaf tag

In order to do pagination in Leaf, please make sure to add the Leaf tag:

public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
    services.register { _ -> LeafTagConfig in
        var tags = LeafTagConfig.default()
        tags.use([
            "offsetPaginator": OffsetPaginatorTag(templatePath: "Paginator/offsetpaginator")
        ])

        return tags
    }
}

If you want to fully customize the way the pagination control are being generated, you are free to override the template path.

QueryBuilder

To return a paginated result from QueryBuilder, you can do the following:

router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
    return Galaxy.query(on: req).paginate(on: req)
}

Array

For convenience, Paginator also comes with support for paginating Array:

router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
    let galaxies = [Galaxy(), Galaxy(), Galaxy()]
    return galaxies.paginate(on: req)
}

RawSQL

Paginator also comes with support for paginating raw SQL queries for complex expressions not compatible with Fluent.

Simple example using PostgreSQL:

router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
    return req.withPooledConnection(to: .psql) { conn -> Future<OffsetPaginator<Galaxy>> in
        let rawBuilder = RawSQLBuilder<PostgreSQLDatabase, Galaxy>(
            query: """
                SELECT *
                FROM public."Galaxy"
            """, countQuery: """
                SELECT COUNT(*) as "count"
                FROM public."Galaxy"
            """, connection: conn)
        return try rawBuilder.paginate(on: req)
    }
}

Note: the count query is expected to have a result with one column named count and with the total columns value in the first row

Leaf tags

To use Paginator together with Leaf, you can do the following:

struct GalaxyList: Codable {
    let galaxies: [Galaxy]
}

router.get("galaxies") { (req: Request) -> Response in
    let paginator: Future<OffsetPaginator<Galaxy>> = Galaxy.query(on: req).paginate(on: req)
    return paginator.flatMap(to: Response.self) { paginator in
        return try req.view().render(
            "MyLeafFile", 
            GalaxyList(galaxies: paginator.data ?? []), 
            userInfo: try paginator.userInfo(),
            on: req
        )
        .encode(for: req)
    }
}

Please note how the Paginator data is being passed in using userInfo on the render call. Forgetting to pass this in will result in an error being thrown.

Then in your MyLeafFile.leaf you could do something like:

<ul>
    #for(galaxy in galaxies) {
        <li>#(galaxy.name)</li>
    }
</ul>

#offsetPaginator()

Calling the Leaf tag for OffsetPaginator will automatically generate the Bootstrap 4 HTML for showing the pagination controls:

<nav class="paginator">
    <ul class="pagination justify-content-center table-responsive">
        <li class="page-item">
            <a href="/admin/users?page=16" class="page-link" rel="prev" aria-label="Previous">
                <span aria-hidden="true">ยซ</span>
                <span class="sr-only">Previous</span>
            </a>
        </li>
        <li class="page-item "><a href="/admin/users?page=1" class="page-link">1</a></li>
        <li class="disabled page-item"><a href="#" class="page-link">...</a></li>
        <li class="page-item "><a href="" class="page-link">12</a></li>
        <li class="page-item "><a href="" class="page-link">13</a></li>
        <li class="page-item "><a href="" class="page-link">14</a></li>
        <li class="page-item "><a href="" class="page-link">15</a></li>
        <li class="page-item "><a href="" class="page-link">16</a></li>
        <li class="page-item  active "><a href="" class="page-link">17</a></li>
        <li class="page-item "><a href="/admin/users?page=18" class="page-link">18</a></li>
        <li class="page-item">
            <a href="/admin/users?page=18" class="page-link" rel="next" aria-label="Next">
                <span aria-hidden="true">ยป</span>
                <span class="sr-only">Next</span>
            </a>
        </li>
    </ul>
</nav>

Transforming

The data in an OffsetPaginator can be transformed by mapping over the paginator and transforming each element at a time:

Galaxy.query(on: req).paginate(on: req).map { paginator in
    paginator.map { (galaxy: Galaxy) -> GalaxyViewModel in 
        GalaxyViewModel(galaxy: galaxy)
    }
}

You can also transform a whole page of results at once:

Galaxy.query(on: req).paginate(on: req).map { paginator in
    paginator.map { (galaxies: [Galaxy]) -> [GalaxyViewModel] in 
        galaxies.map(GalaxyViewModel.init)
    }
}

In case the transformation requires async work you can do:

Galaxy.query(on: req).paginate(on: req).map { paginator in
    paginator.flatMap { (galaxies: [Galaxy]) -> Future<[GalaxyViewModel]> in 
        galaxies.someAsyncMethod()
    }
}

Configuration

The OffsetPaginator has a configuration file (OffsetPaginatorConfig) that can be overwritten if needed. This can be done in configure.swift:

public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
    // ..
    services.register(OffsetPaginatorConfig(
        perPage: 1,
        defaultPage: 1
    ))
}

๐Ÿ† Credits

This package is developed and maintained by the Vapor team at Nodes.

๐Ÿ“„ License

This package is open-sourced software licensed under the MIT license

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].