Overview

Here we will see the entire process of building a data fetching function according to specific API capabilities.

The external API

For example, an API offering these parameters for querying data:

https://api.mysite.com/users?
    limit=10            # rows per page
    &offset=20          # offset (20 = page number 3)
    &q=michel           # full text search
    &city=limoge        # column filter: where "city" = 'limoge'
    &sort=age
    &order=desc         # order by "age" descending

Bind your data fetching function to the TableHandler

Once you instantiated a new TableHandler, you have to specify a data fetching function using the load method. This function is a callback accessing a state argument, which represents the client-side state of the datatable.

Your data fetching function will run every time a change occurs, such as when a user sorts or filters the data.

<script lang="ts">
    import { type State, TableHandler } from '@vincjo/datatables/server'
    import { myFunction } from './api'

    const table = new TableHandler([], { rowsPerPage: 10 })

    table.load((state: State) => myFunction(state): Promise<Row[]> )
</script>

State (= client-side table state)

The state argument reprensents a snapshot of the datatable:

type State = {
    currentPage: number,
    rowsPerPage: number,
    offset: number,
    search: string | undefined,
    sort: { field: string, direction: 'asc' | 'desc' } | undefined,
    filters: { field: string, value: unknown }[] | undefined,
    setTotalRows: (value: number) => void
}

The wrapper function

Here is an example of translation from client-side state to a proper URL query string.

import type { State } from '@vincjo/datatables/server'

export const myFunction = async (state: State) => {

    const response = await fetch(
        `https://api.mysite.com/users?${getParams(state)}`
    )
    const json = await response.json()
    state.setTotalRows(json.count)
    return json.rows
}

const getParams = ({ offset, rowsPerPage, search, sort, filters }: State) => {
    let params = `offset=${offset}&limit=${rowsPerPage}`
    if (search)     params += `&q=${search}`
    if (sort)       params += `&sort=${sort.field}&order=${sort.direction}`
    if (filters)    params += filters.map(({ field, value }) => `&${field}=${value}`).join()
    return params
}

Trigger reload

table.invalidate()” runs your data fetching function and updates table rows.

table.invalidate()