-
Notifications
You must be signed in to change notification settings - Fork 143
Column schema
Understand first of all that we are dealing with two different (but similar) schema
objects:
-
dataModel.schema
- Hypergrid's column schema -
filter.schema
- Legacy filter's data transformer column schema
This is the schema used by Hypergrid to identify columns.
Typically Hypergrid apps use one of the following patterns:
- The application developer is encouraged to supply a custom schema (see Custom data model schema below).
- Alternatively, you can call a utility function to derive a schema from the JSON data with friendly column headers derived from the column names (see Explicitly derived data model schema below).
- As a fallback, if you do not provide any schema at all, the "JSON" data model will derive a basic schema for you from the JSON data (see Implicitly derived data model schema below).
Pass your schema to one of:
- The
new Hypergrid()
constructor - A
setData()
call
var grid = new Hypergrid({ data: data, schema: getSchema(data) });
// or:
var grid = new Hypergrid; // and then later:
grid.setData({ data: data, schema: getSchema(data) });
If you do not provide a schema, one will be derived for you from the JSON data by the data model if you do not provide one. This automatically derived schema contains only the field (column) names and nothing else. The field names are displayed in the column headers (column header text). This implicit algorithm uses the fields.getFieldNames()
utility function.
There is another utility function getSchema()
, which when called explicitly derives a schema that includes friendlier headers: The headers are derived from the column names, separating words implied by camelCase or hyphens or underscores, and captalizing each resulting word. getSchema
uses both the fields.getFiedNames()
and the fields.titleize()
utility functions.
Where to find getSchema
:
If using the fin-hypergrid
npm module and Browserify:
var getSchema = require('fin-hypergrid/src/lib/fields.js').getSchema;
If using the fin-hypergrid.js
build file:
<script src="https://fin-hypergrid.github.io/core/2.0.2/build/fin-hypergrid.js"></script>
var getSchema = fin.Hypergrid.lib.fields.getSchema;
A custom schema is a complete array of column specification objects. This should be a complete array of filter schema specification objects, including hidden fields (so they will be available to the user for unhiding later).
var customSchema = [
{ name: 'lastName', header: 'Last Name' },
{ name: 'firstName', header: 'First Name' },
... // etc.
];
setData( data: data, schema: customSchema });
name
is required; header
is optional. Other optional members include type
; and calculator
for computed columns.
The other kind of schema is for the legacy filter data transformer.
NOTE: Basic information about the legacy filter transformer's plug-in and schema is provided here as a courtesy. This transformer is not part of the Hypergrid open source project and specifically is not maintained by Openfin.
The legacy filter schema was developed independently from the data model schema. Consequently, the filter schema column specification objects are (slightly) different in structure than the data model schema column specification objects. Specifically, the filter schema column specs:
- May consist of a simple string primitive. Such a string serves as a stand-in for an object with a single member,
name
, set to that string primitive, i.e.,{ name: '...' }
. - The member name for the column header text string is
alias
rather thanheader
. - May be organized into a hierarchy, meaning that any spec in the list may itself be a "sublist" of specs. The purpose of these nested lists is to organize the columns into groups and subgroups for the user's convenience. For example, any drop-downs generated from the schema will be rendered in HTML with
<optgroup>
tags. (Note however that due to browser limitations, do not nest your columns any deeper than one additional level.) - May include additional properties to control the filter's behavior. For example, whether search arguments should be considered case sensitive or not. These properties are specific to the filter you are using and are beyond the scope of this document.
As with the data model schema, you can (and perhaps should) fashion your own filter schema. Alternatively, the HyperFilter plugin can derive it for you.
To use the legacy filter, you must perform the following 4 steps:
- Make sure your data model knows how to filter data (knows what to do with
'filter'
prop calls) - Install the legacy filter plug-in
- Create a "filter" data controller
- Attach the "filter" data controller to the data model
These steps are details in the following subsections:
The standard data model can filter data with the datasaur-filter
is in its data transformation pipeline:
If using the datasaur-filter
npm module and Browserify:
grid.setPipeline([
require('datasaur-filter'),
... // other data transformers
]);
If using the datasaur-filter.js
build file:
<script src="http://joneit.github.io/datasaur-indexed/build/edge/datasaur-indexed.js"></script>
<script src="http://joneit.github.io/datasaur-filter/build/edge/datasaur-filter.js"></script>
(Note that datasaur-filter depends on datasuar-index.)
grid.setPipeline([
window.datasaur.filter,
... // other data transformers
]);
If using the fin-hypergrid
npm module and Browserify:
grid.setPipeline([
require('fin-hypergrid/add-ons/hyper-filter'),
... // other data transformers
]);
If using the hyper-filter.js
build file:
<script src="https://fin-hypergrid.github.io/core/1.3.0/build/add-ons/hyper-filter.js"></script>
var plugins = [
fin.Hypergrid.Hyperfilter,
... // other plug-ins
];
You provide your plugins
to one of:
- The
new Hypergrid()
constructor - An
installPlugins()
call
var grid = new Hypergrid({ data: data, ..., plugins: plugins });
// or:
var grid = new Hypergrid({ data: data, ... });
grid.installPlugins(plugins);
The plug-in's create()
method takes a provided schema (or no schema) and returns a filtering data controller interface with the schema embedded within it:
var filterController = hyperfilter.create(schema};
schema
may be one of:
- Omitted (
undefined
) which will derive a schema for you from Hypergrid's column objects (which were derived from the data model schema). - A custom filter schema. This should be a complete array of filter schema specification objects, including hidden fields (so they will be filterable if unhidden later).
- A function.
If you provide a function, the function is called with the instantiated columnSchemaFactory
object as context:
-
this.schema
array - The derived schema. -
this.organize
method - Automatically nests the schema based on column name prefixes. -
this.sort
method - Sorts the schema, optionally moving all the optgroups to the top or bottom. -
this.overlay
method - Overlays a custom schema on top of the derived schema. This is an easy way to make sure columns not included in your schema (e.g., hidden columns) are actually included so they will be known to the filter.
Your function is free to reorganize or completely replace this.schema
. There is no return value (any returned value is discarded).
Howsoever create
is called, it returns a filter controller interface that references the schema. The following utility methods are added to the schema
array object (click links for more details):
-
[schema.walk(iteratee)](http://joneit.github.io/pop-menu/popMenu.html#.walk)
iterates through the (possibly hierarchical) array. A defined return value replaces the element. -
[schema.lookup(name)](http://joneit.github.io/pop-menu/popMenu.html#.lookup)
finds the element in the (possibly hierarchical) array with the provided name.
If you provide a function, these utility methods are added to the factory's this.schema
before it is called, making them available within your function.
In any case, the filter controller then adds the utility methods if they are not already present. This ensures that custom schema always have them.
grid.filter = filterController;
The above grid.filter
is actually a setter, some syntactic sugar mixed in by the plug-in. What's really going on here is this:
grid.setController('filter', filterController);
It is possible to create a single custom schema that can be used by both the data model and the legacy filter by observing the following two rules;
- Avoid nesting your schema. (The data model schema does not support hierarchical structure.)
- For header cell text, always provide both an
alias
and aheader
property.
Hypergrid's Column
objects have setters for header
, type
, and calculator
which dynamically update both the data model schema and all the data model's attached data controllers via their respective properties()
methods. (Note that the filter data controller's properties()
method automatically translates header
into alias
.)
It is recommended that you "bring your own" schema. This gives you complete control of the schema.
var customSchema = [
'name',
'birth_year'
];
// in place of string primitives you can give an filter specification objects:
customSchema = [
{ name: 'name' },
{ name: 'birth_year', type: 'number' }
];
Following also demonstrates the use of the organize
and lookup
methods of CustomSchemaFactory
.
function derivedPeopleSchema() {
// create a hierarchical schema organized by alias
this.organize(/^(one|two|three|four|five|six|seven|eight)/i, { key: 'alias' });
// set some column-specific properties
var columnSchema;
if ((columnSchema = this.lookup('last_name'))) {
columnSchema.defaultOp = 'CONTAINS'; // default filter cell operator
}
}
The "pink" demo now includes an example of superimposing a custom schema on top of a derived schema so that non-active columns can easily be included in a custom schema:
function superimposedCustomSchema() {
this.overlay(customSchema);
}