Options
When building forms, there are many cases where you will want to present the end user with a list of options from which a value can be selected. The Options
class is available in the Node.js libraries for Editor to fulfill this need. It is attached to an individual field using Field.options()
and will resolve, based on its configuration, to a list of options for the field.
The following built-in field types can make use of the resulting options:
Options class
The Options
class allows the list of options to be retrieved in a number of different ways:
- From a database
- A statically defined list of options
- A custom function
The class also has a number of control methods available to define how it should operate for actions such as autocomplete and tags search, label display rendering and so on. See the "Control methods" section below for more details.
Attaching to a field
Each field in an Editor instance can have an Options
class assigned to it through its Field.options()
method - e.g.:
Field.options( new Options () )
Constructor
The constructor can be given with the following overloads:
new Options()
- Empty initialisation, use the class methods to define behaviour.new Options(table: string, value: string, label: string)
- Set the most common database options in the constructor.new Options(fn)
- Set a custom function to get the options.
The result is that the following two instances are equivalent:
new Options(table, value, label);
new Options()
.table(table)
.value(value)
.label(label);
Database methods
The most common use for the Options
class is to read a list of options from a database. The following methods are available to configure that interaction. Please note that when used as a setter (as described here), all methods return the class instance to allow easy chaining of methods.
label()
.label( label: string|string[] ): Options
Specify the column(s) that should be used for the label of an option pair (label/value). This is what the end user would see in the list of options. In many cases (but not all!) the label and value are not the same value - the value might be a row identifier, while the label is a human readable representation.
If given as a string, multiple columns will be read and can be used in the .render()
function to present a label of arbitrary complexity.
leftJoin()
.leftJoin( table: string, column1: string, operator: string, column2: string ): Options
Provides a join to a second database table, allowing extra information to be looked up (typically for the label if needed). This method has the same signature as the Editor.leftJoin()
method and directly maps to an SQL left join statement.
table()
.table( table: string ): Options
Set the database table name that the list options should be read from.
value()
.value( val: string ): Options
Set the column name that contains the value for each option pair (label/value). Typically this would be a primary key column in the table.
where()
.where( condition: callable ): Options
Function that will apply conditions to the list of options (i.e. a WHERE
statement), allowing only a sub-set of the options to be selected. Please refer to the Knex.js documentation for full details of the conditional methods that can be used in this function.
Custom data methods
The following methods can be used to obtain the data for the options from a location other than a database.
add()
.add( label: string, value: string ): Options
Add static options to the list. This can be used alongside the database methods listed above to combine static options and the database retrieved data, or it can be used on its own. Note that the options here are passed through the rendering, options limit and ordering (i.e. the merge of static and database options is done before those operations are performed).
fn()
.fn( func: Function ): Options
This is function that takes two parameters:
- A
Database
object which can be used to perform custom lookups if needed (e.g. against a stored procedure or for cases with a complex query is required that cannot be constructed with the methods above). - A search terms - used for the
autocomplete
andtags
field types. The function should limit the returned options objects to those that match this term (can benull
if no filtering is needed).
The return should be an array of objects, which contain label
and value
properties. Please note that unlike .add()
the options returned by this method do not get merged with those from the database. This method provides you with complete control of the options to return to the client-side, and thus does not do any ordering or rendering.
Control methods
The following methods are used to control the operations that the Options
class performs.
alwaysRefresh()
.alwaysRefresh( set: boolean ): Options
Set the flag to indicate if the options should always be refreshed (i.e. on get, create and edit) or only on the initial data load (false
). Default is true
(always refresh) and allows the list of options to take account of any changes that an editing action might cause (e.g. a new option, change in label, etc). The benefit of disabling this option is that one less query is performed on editing actions, which can help (albeit only a small amount) with performance, if you know the list of options won't change.
render()
.render( renderer: callable ): Options
A formatting function that will be applied to each label read from the database this is particularly useful if you get multiple columns with .label()
and wish to customise how those fields are shown. They will simply be concatenated with a single space character if no function is provided. The function is called once for each option and is passed the database row for the option in question. A string must be returned.
include()
.include( column: string|string[] ): Options
By default the object for each option will contain only label
and value
properties, but you may wish to have extra information, particularly if you are doing client-side rendering for the labels. This method lets you specify column names from value()
and label()
that should be included in the output object for each option, in addition to the value and label.
limit()
.limit( set: integer ): Options
Limit the number of results that are returned. If this method is not used, no limit will be imposed.
order()
.order( set: string|boolean ): Options
Specify an SQL order by clause that will determine the order of the options. If this method is not used the ordering will be automatically performed on the rendered data (which is the same as passing in true
). Ordering can be disabled by passing false
to this method (since 2.4).
searchOnly()
.searchOnly( set: boolean ): Options
By default options will be read and returned for any field that has an Options
class assigned to it. In the majority of cases this is what you want (e.g. select
), but in some cases, the options might only be relevant once the user starts typing. You may wish to have this behaviour when using the built-in autocomplete
and tags
field types.
Examples
The following example shows the most simple used case with a list of options returned from the sites
database table:
new Field('users.site')
.options(
new Options('sites, 'id', 'name')
);
Using the chaining API, the same can be written as:
new Field('users.site')
.options(new Options()
.table('sites')
.value('id')
.label('name')
);
To apply a condition to the data retrieval we can make use of the .where()
method. In the below, getting only names
which start with the letter 'L':
new Field('users.site')
.options(new Options()
.table('sites')
.value('id')
.label('name')
.where(function() {
this.where('name', 'LIKE', 'L%')
})
);
The following makes use of a rendering function to combine multiple fields for display as the label. In this case the resulting format is: 'name (country)' - e.g.: 'Edinburgh (UK)':
new Field('users.site')
.options(new Options()
.table('sites')
.value('id')
.label(['name', 'country'])
.render(row => {
return row.name + ' (' + row.country + ')';
})
);
Custom function
As a closure function, the Options
provides the ability to get the data for the field options from virtually anywhere (files, arrays, web-services, database, etc) - you define the code that will return an array of options. By default the returned array should contain value/label
options for each entry (although this can be customised using the options of the fields such as select
).
The following example shows a static array of values being returned:
new Field('users.site').options(() => {
return [
{value: 'EDI', label: 'Edinburgh'},
{value: 'LON', label: 'London'},
{value: 'NEW', label: 'New York'},
{value: 'SAN', label: 'San Francisco'}
];
});
Node.js API documentation
The Node.js API developer documentation for the Editor Node.js classes is available for detailed and technical discussion about the methods and classes discussed above.