View Source Computed Fields

In some cases you want to compute new fields based on existing fields. Backpex adds a way to support this.

Configuration

There is a select option you may add to a field. This option has to return a dynamic. This query will then be executed to select fields when listing your resources. In addition this query will also be used to order / search this field.

# in your resource configuration file

@impl Backpex.LiveResource
def fields do
[
    total: %{
        module: Backpex.Fields.Integer,
        label: "Total",
        select: dynamic([post: p], fragment("likes + dislikes")),
    }
]
end

The example above will compute the value of the total field based on the likes and dislikes fields.

Example

Imagine there is a user table with first_name and last_name. Now, on your index view you want to add a column to display the full_name. You could create a generated column in you database, but there are several reasons for not adding generated columns for all computed fields you want to display in your application.

You can display the full_name of your users by adding the following field to the resource configuration file.

# in your resource configuration file

@impl Backpex.LiveResource
def fields do
[
    full_name: %{
        module: Backpex.Fields.Text,
        label: "Full Name",
        searchable: true,
        except: [:edit],
        select: dynamic([user: u], fragment("concat(?, ' ', ?)", u.first_name, u.last_name))
    }
]
end

We are using a database fragment to build the full_name based on the first_name and last_name of an user. Backpex will select this field when listing resources automatically. Ordering and searching works the same like on all other fields, because Backpex uses the query you provided in the dynamic in order / search queries, too.

We recommend to display this field on index and show view only.

Important

Note: You are required to add a virtual field full_name to your user schema. Otherwise, Backpex is not able to select this field.

Computed Fields with Associations

Computed fields also work with associations.

For example, you are able to add a select query to a Backpex.Field.BelongsTo field.

Imagine you want to display a list of posts with the corresponding authors (users). The user column should be a full_name computed by the first_name and last_name:

# in your resource configuration file

@impl Backpex.LiveResource
def fields do
[
    user: %{
        module: Backpex.Fields.BelongsTo,
        label: "Full Name",
        display_field: :full_name,
        select: dynamic([user: u], fragment("concat(?, ' ', ?)", u.first_name, u.last_name)),
        options_query: fn query, _assigns ->
            query |> select_merge([user], %{full_name: fragment("concat(?, ' ', ?)", user.first_name, user.last_name)})
        end
    }
]
end

We recommend to add a select_merge to the options_query where you select the same field. Otherwise, displaying the same values in the select form on edit page will not work.

Do not forget to add the virtual field full_name to your user schema in this example, too.