DataProvider (DataProvider v1.0.0) View Source

Library for simple and comfortable working with table data.

This library implements API for generate and manipulate data

Example

Firstly, You have to make a DataProvider implementation module, like:

defmodule MyDataLoadModule do
  # Change current module declaration with `DataProvider`
  use DataProvider

  # Function which required to return Repo implementation if you
  # plan to return `Ecto.Query` in `find/1`.
  # If your `find/1` gonna return not a `Ecto.Query` then defining
  # `repo/0` have no make sense.
  def repo(), do: MyRepo

  # Searching logic, receives `DataProvider` and have to return `Ecto.Query` or `list()`
  # This function have to implement only searching, with no orders, offsets and limits.
  def find(%DataProvider{search_options: %_{options: %{"title" => title}}),
    do: Ecto.Query.from(p in Posts, where: p.title == ^title)
  def find(%DataProvider{}), do: Ecto.Query.from(p in Posts)
end

When you declared your DataProvider implementation, you can use it as adapter for manipulate data.

defmodule MyController do
  use MyAppWeb, :controller
  import DataProvider

  def index(%Plug.Conn{query_params: query_params, path_params: path_params} = conn, _params) do
    # Getting a custom user filtering params (it have to be map). By default,
    # `DataProvider` already contain initial state of searching
    # options (they are empty, no filter, no sorting, nothing).
    received_filter_params = Map.get(query_params, "filter", %{})

    # Trying to get `page` value from user request. By default `DataProvider` already
    # stay in first page position and configurated for 15 items per page.
    page = Map.get(path_params, "page", 1)

    # * `filter(received_filter_params)` - set new filtering params for current `DataProvider`
    # and return updated `DataProvider`.
    # * `change_page(page)` - set new value of page number
    # * `init()` - accept all of your changes and calculate data in the provider.
    data_provider = MyDataLoadModule.data_provider()
                    |> filter(received_filter_params)
                    |> change_page(page)
                    |> init()

    # Usual rendering function
    render(conn, "index.html", data_provider: data_provider)
  end
end

This is example of using the DataProvider in Phoenix application, what we have done:

As you see, definition of MyController.index/2 is typical, we will not stop on it, you can find more information here. I'd only add, that we have declared query_params and path_params variables, they are useful for this example, but it isn't required to.

Finally you will got a struct DataProvider, looks like:

%DataProvider{
  module: MyDataLoadModule,
  data: %DataProvider.Data{
    total_count: 42,
    items: [
      ...
      %Posts{},
      %Posts{},
      %Posts{},
      ...
    ]
  },
  search_options: %DataProvider.SearchOptions{
    options: %{
      "description" => "some find string"
    },
  },
  sort: %DataProvider.Sort{
    options: []
  }
  pagination: %DataProvider.Pagination{
    page: 2,
    page_size: 15
  }
}

This structure contain all required data for using it in another cases, like an rendering the data table, returning it by REST-full API, live-reload functionality and etc.

Link to this section Summary

Functions

Using function of this module macro

Function for creating new data provider by search options and module configurations.

Add new filter params for data provider

Returns DataProvider with loaded new page.

Initialization function, needs for reload actual state of dataprovider.

Return current page number of DataProvider

Reloads dataprovider. Required for stateful data providers.

Add new sorting params for data provider

Link to this section Types

Specs

t() :: %DataProvider{
  data: DataProvider.Data.t(),
  module: :not_implemented | any(),
  pagination: DataProvider.Pagination.t(),
  search_options: DataProvider.SearchOptions.t(),
  sort: DataProvider.Sort.t()
}

Type of DataProvider

Contains:

  • module - Module atom which implements DataProvider. By default equal :not_implemented.

  • data - DataProvider.Data struct with result of data selection and processing.

  • search_options - struct DataProvider.SearchOptions contains all searching params for exactly this data provider.

  • sort - struct DataProvider.Sort contains all sorting params for exactly this data provider.

  • pagination - DataProvider.Pagination contains state of current of DataProvider and implements all business logic of calculating page sizes, page counts, offsets, limits and etc.

Link to this section Functions

Link to this macro

__using__(args)

View Source (macro)

Using function of this module macro

Link to this function

change_page(data_provider, page, opts \\ [])

View Source

Specs

change_page(t(), integer(), Keyword.t()) :: t()

Returns DataProvider with changed page.

Args

  • data_provider - DataProvider instance.

  • page - integer value with new page for setting.

  • opts - keyword with function options.

Accept values of opts

  • :instant - boolean value. If :instant is true then current data provider will be reloaded instantly, otherwise search params will be loaded with no reloading (for actualizing data provider you will be have to call init/1). By default is false.
Link to this function

create(search_options \\ %{}, opts \\ [])

View Source

Specs

create(map(), Keyword.t()) :: t()

Function for creating new data provider by search options and module configurations.

Link to this function

filter(data_provider, params \\ %{}, opts \\ [])

View Source

Specs

filter(t(), map(), Keyword.t()) :: t()

Add new filter params for data provider

Args

Accept values of opts

  • :merge - boolean value, which affect on new searching options. By default - false, if merge is false - passed searching options will replace search options in exist data provider. If true - will merge.

  • :instant - boolean value. If :instant is true then current data provider will be reloaded instantly, otherwise search params will be loaded with no reloading (for actualizing data provider you will be have to call init/1). By default is false.

Link to this function

go_to_page(data_provider, page)

View Source

Specs

go_to_page(t(), integer()) :: t()

Returns DataProvider with loaded new page.

This function works similar page/2 with one difference.

This function are not wait calling init/1. Calling the go_to_page/2 reloads data provider right away.

Specs

init(t()) :: t()

Initialization function, needs for reload actual state of dataprovider.

Calling this function will reload inner data and actualize all inner indexes.

This function was separated to independent mechanism for sparingly using a resources.

Link to this function

page_number(data_provider)

View Source

Specs

page_number(t()) :: integer()

Return current page number of DataProvider

Specs

reload(t()) :: t()

Reloads dataprovider. Required for stateful data providers.

Link to this function

sort(data_provider, params \\ [], opts \\ [])

View Source

Specs

sort(t(), Keyword.t(), Keyword.t()) :: t()

Add new sorting params for data provider

Args

  • data_provider - DataProvider instance

  • params - map with new sorting params. Value of this argument will be passed into DataProvider.Sort

  • opts - keyword with filtering options.

Accept values of opts

  • :merge - boolean value, which affect on new searching options. By default - false, if merge is false - passed searching options will replace search options in exist data provider. If true - will merge.

  • :instant - boolean value. If :instant is true then current data provider will be reloaded instantly, otherwise search params will be loaded with no reloading (for actualizing data provider you will be have to call init/1). By default is false.