Defining fields

Adding fields

There are 2 ways of defining fields, both are done in the setup() method of your Table class.

You can either return an array of fields or use addField($name, $properties).

Returning an array (overwrite)

If the fields() method of your Table class return an array it will overwrite the $fields property of your instance:

public function setup()
    {
        return [
            'id' => $this->newField()->set([
                'title' => 'ID',
                'column' => 'id',
                'sortable' => true,
                'searchable' => false
            ]),
            'email' => $this->newField()->set([
                'title' => 'E-mail',
                'column' => 'email',
                'sortable' => true,
                'searchable' => true
            ]),
        ];
    }

Adding fields (append)

calling addField($name, $properties) will append fields to your instance:

public function setup()
    {
        $this->addField('id', [
            'title' => 'ID',
            'column' => 'id',
            'sortable' => true,
            'searchable' => false
        ]);
        $this->addField('email', [
            'title' => 'E-mail',
            'column' => 'email',
            'sortable' => true,
            'searchable' => true
        ]);
    }

Properties

There are plenty of options you can set as properties on your fields. Some can be defined on their own, some need others in order to work.

Here's an overview of several use cases:

Title (optional)

This property takes a string, as you might have guessed, it's used to set the column's title in your table's <thead>.

If you'd rather set this yourself in you're table's HTML tag, you can forget about this property.

'title' => 'Some string',

Sortable (optional)

Should this column be sortable? This property defaults to false.

'sortable' => true,

Searchable (optional)

Should this column be searchable? This property defaults to false.

'searchable' => true,

Default (optional)

This option allows you to define default content for a column.
The default content will be rendered if the data isn't set (as in NULL or if no column/select property was defined).

'default' => 'No result',

Retrieving field data

There are several ways you can set up a field's data retrieval:

  • by a column name
  • by a select statement
  • leave it empty

Before I start explaining them I'd like to mention that there are 2 handy 'variables' you can insert in your columns or selects:

  • (:table) the table's name of the column
  • (:primary_key) the name of the model's primary key column

If the column has a relation key defined, it will try to use the relation's data instead of the specified model's.

By Column name

Let's say we have a blog and want to display a list of posts.

If you want something as simple as just a column from your database you could define it like so (in this case we'll select the title field).

'column' => 'title'

This is technically correct, but to help you keep yourself sane while debugging I would advise you to adding (:table). before title. If you're not making use of relations (:table) will be replaced with the model's table name.

Of course, if you've also loaded relations you could and you know their model's table name you could replace (:table) with that to be sure the column you want gets selected.

In case you don't know your relation's model's table name you could define a relation property.
Let's say we'll add a second field to our table with the post's author's name:

'column' => '(:table).name',
'relation' => 'author',

This would work fine if we're sure that the namecolumn is only present in the relation's table.
If the model's table also has a name column we'll need to make sure Eloquent knows which one we're talking about.

This can be done easily by adding an as property:

'column' => '(:table).name',
'relation' => 'author',
'as' => 'author_name'

Now we're 100% sure that the author's name won't conflict with any other relations or the model's columns.

By select statement

If you want more flexibility you have the option of doing a raw SQL select, for example, looking back at our previous example. What if, instead of just a name, the author has a first_name and a last_name.

You could make 2 separate fields for them, but searching might be easier if they're together. So let's concatenate them:

'select' => 'CONCAT((:table).first_name, \' \', (:table).last_name)',
'as' => 'author_name'

Of course a relation could be defined here as well.

By leaving it empty

Of course defining a way to retrieve data isn't always needed, for example, when you want a column in your table that just shows a few buttons or a checkbox, to offer some data interaction.

In this case we wouldn't define any of the following properties column, relation, select, as. No, would be better to either define a default property that sends over default content (I would advise against this when you're working with large data sets) or you could define a render function.

Presenting data

You are able to present your data in 3 different ways:

  • as-is (just the values you get from the database)
  • by formatting the data and sending it over in the request
  • by rendering the data on the client side

You can make use of the last 2 options in 2 different ways. I'll give you a quick overview before explaining them further:

Table method definition

Your Table class will search for a render and a format method for each field you've defined. These methods would be defined in the following format:

  • the method's name name has to start with 'get'
  • next it will change the column's name to camel case (title would become Title, created_at would become CreatedAt)
  • the method's name should end with 'Format' or 'Render'

Anonymous function

If you're the quick and dirty type of programmer there's the option to assign an anonymous function to either the format' or renderproperty which takes the same parameters as theTable` method definition.

Data formatting (orthogonal data)

Sometimes you wish to format a column that you send in a request, for example, you wanted to send over a created_at field. It's value is perfect for ordering, but it's not necessarily that human-friendly. In this situation it would make perfect sense to format the data and send the original value over for sorting.

You'll have to create a method first on your Table instance so it knows that you want to format a specific field.

We would be adding getCreatedAtFormat($data, $record). The first parameter $data would be the actual value of created_at (in this case, eloquent will provide us with a Carbon object), while the second parameter contains all of the data in the same row.

public function getCreatedAtFormat($data, $record) {
    return $data->format('D m/d/Y H:i');
}

You should keep in mind that when you define a formatter and a renderer, the renderer will be ignored.

Client side field rendering

DataTables allows you to define functions that render your column's content, just as data formatting, there are 2 ways you can do this:

  1. By assigning the the format key an anonymous function
  2. By defining a getFieldNameRender method in your Table definition

Both get 1 parameter $field which is the actual definition you assigned it.

Example

Let's say we have a title column, but we'd like the data in this column to be wrapped in a <strong> tag,
in our case we'd need to create a new public method called getTitleRender($field).

The only parameter you'll get is the instance of the field definition.

in the method we'll have to return a string or an object that uses __toString() (like View).

public function getTitleRender($field)
{
    return 'return "<strong>"+row.title+"</strong>";';
}

Any string you define there gets wrapped in the following functions:

function(data, type, row, meta)
{
  ----- Render method content -----
}