-
Notifications
You must be signed in to change notification settings - Fork 1
Model Definition
Complete example of the model configuration file: contracts model.
Model Definition is an object describing an entity. It has the following shallow structure:
const modelDefinition = {
model: {
name,
fields,
validate,
translations
},
permissions: {
crudOperations
},
api: {
get,
search,
delete,
create,
update
},
ui: {
search: () => ({ searchableFields, resultFields }),
create: { defaultNewInstance, formLayout },
edit: { formLayout },
show: { formLayout },
instanceLabel,
customOperations,
spinner
}
}
modelDefinition.model.name
A required string (usually singular entity name), like "contract"
or "vehicle"
.
modelDefinition.model.fields
A required object describing model fields.
{
<field name>: {
/*
* At least one field must have "unique" property set to true.
*/
?unique: <boolean, whether the field is a part of Logical Key, false by default>,
?type: <string, field type (see corresponding "Terminology" section)>,
/*
* Constraints for field validation.
* Their allowed set and tuning parameters of each constraint depend on field type.
* Constraints are usually called after field input's "onBlur" event
* and before saving instance modifications.
*/
?constraints: {
?max: <number|date, max length for strings or max value for dates/numbers>,
?min: <number|date, min length for strings or min value for dates/numbers>,
?required: <boolean, whether the field value can be empty>,
?email: <boolean>,
?matches: <regexp>,
?url: <boolean>,
/*
* Custom field-validator returning boolean true in case of successful validation,
* or throwing an array of errors (or single error object) if validation failed.
*/
?validate(<serializable, field value>, <object, entity instance>) {
...
throw [<Field Validation Error>, ...];
...
return true;
}
}
},
...
}
modelDefinition.model.translations
An optional object with translations for labels/messages defined in the model. Its shape should correspond to preferred format for @opuscapita/i18n library.
Translation keys convention:
Translation Target | Translation Key | Default translation |
---|---|---|
Model name (shown in the header) | "model.name" |
"model.name" |
Model tab label | "model.tab.<tab name>.label" |
titleCase("<tab name>") |
Model section label | "model.section.<section name>.label" |
titleCase("<section name>") |
Model field label | "model.field.<field name>.label" |
titleCase("<field name>") |
Model field hint | "model.field.<field name>.hint" |
- |
Model field tooltip | "model.field.<field name>.tooltip" |
- |
Custom Field Validation Error | "model.field.<field name>.error.<error id>" |
error.message || error.id |
Instance Validation Error | "model.error.<error id>" |
error.message || <built-in error message> |
titleCase() converts its arugment from camelcase to titlecase, ex. titleCase("maxOrderValue") === "Max Order Value"
.
React context must have i18n
property with I18nManager as its value.
modelDefinition.permissions.crudOperations
A required object setting permissions for CRUD operations.
{
?create: <boolean|function>, // false by default
?edit: <boolean|function>, // false by default
?delete: <boolean|function>, // false by default
?view: <boolean|function>, // false by default
}
At least one property must be set to true
or defined as a function.
In case of a boolean, a permission sets editor-wise user permission for a specific operation, ex.
{
create: true,
delete: false,
...
}
In case of a function, a permission operates in two modes, depending on a number of function arguments:
Mode name | Function arguments | Function return value |
---|---|---|
global | - | sets editor-wise user permission for a specific operation |
per-instance | <object, entity instance> |
sets instance-wise user permission for a specific operation |
Editor-wise permission is checked before instance-wise one, therefore if global premission is false
then per-instance permission is ignored.
If specified, edit
and delete
permission defined as a function must operate in both global and per-instance mode.
If specified, create
and view
permission defined as a function must operate in global mode only.
An example for functions:
{
create: () => {
...
return <boolean>; // editor-wise permission.
},
delete: ({ instance } = {}) => {
if (instance) {
// The function is called in "per-instance" mode.
...
return <boolean>; // instance-wise permission.
} else {
// The function is called in "global" mode.
...
return <boolean>; // editor-wise permission.
}
},
...
}
modelDefinition.api.get
A required async function which gets an entity instance by its Logical Key (usually id).
function({
instance: <object, an entity instance with at least Logical Key fields>
}) {
...
return <promise>;
}
The promise
-
resolves with the entity instance containing all of its fields
{ <field name>: <serializable, field value>, ... }
-
or rejects with an error
{ code: <whole number, error code>, ?payload: <any, structure is defined by error code> }
modelDefinition.api.search
A required async function which searches for entity instances by a criteria.
function({
?filter: {
<field name>: <serializable, filter value for the field>,
...
},
?sort: <string, sort field name>,
?order: <"asc"|"desc", sort order>,
?max: <natural number, search result limit>,
?offset: <whole number, search result offset>
}) {
...
return <promise>;
}
The promise
-
resolves with an object containing information about entity instances satisfying the criteria
{ instances: [{ <field name>: <serializable, field value>, ... }, ...], totalCount: <whole number, total number of filtered entity instances> }
-
or rejects with an error
{ code: <whole number, error code>, ?payload: <any, structure is defined by error code> }
modelDefinition.api.delete
A required async function which deletes entity instances by their Logical Keys (usually ids).
function({
instances: <array[object], entity instances with at least Logical Key fields>
}) {
...
return <promise>;
}
The promise
-
resolves with an object containing information about deleted entities. In case of a failure deleting one or more instances, an optional
errors
property may be specified with an array of error objects. If error object format corresponds to Instance Validation Error, appropriately translated messages are displayed as Notifications. Errors array length may be different from the number of instances failed to be deleted.{ count: <whole number, how many entity instances where actually deleted>, ?errors: [<object>, ...] }
-
or rejects with an error
{ code: <whole number, error code>, ?payload: <any, structure is defined by error code> }
modelDefinition.api.create
A required async function which creates an entity instance.
function({
instance: {
<field name>: <serializable, field value>,
...
}
}) {
...
return <promise>;
}
The promise
-
resolves with the entity instance as created on server-side
{ <field name>: <serializable, field value>, ... }
-
or rejects with an error
{ code: <whole number, error code>, ?payload: <any, structure is defined by error code> }
modelDefinition.api.update
A required async function which modifies an existing entity instance.
function({
instance: {
<field name>: <serializable, field value>,
...
}
}) {
...
return <promise>;
}
The promise
-
resolves with the entity instance as modified on server-side
{ <field name>: <serializable, field value>, ... }
-
or rejects with an error
{ code: <whole number, error code>, ?payload: <any, structure is defined by error code> }
modelDefinition.ui.search().searchableFields
An optional array of objects describing which Persistent Fields should be included in search criteria.
By default, all model.fields are used.
[{
name: <string, persistent field name>,
?render: {
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of component prop with field value>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: {
format: value => <serializable>, // Field Type -> UI Type.
parse: value => <serializable> // UI Type -> Field Type or throw an error.
}
}
}
}, ...]
-
render
has a default for a Persistent Fields of standard Field Type:{ component: <string, id of default FieldInputComponent for displaying the Field Type>, value: { propName: "value", type: <string, UI Type peculiar to the default FieldInputComponent> } }
render
has no default for a field of custom Field Type, so it must be explicitly defined in such a case. -
render.component
is either Custom FieldInputComponent or string id of Embedded FieldInputComponent. -
render.value.type
is redundant for an Embedded FieldInputComponent, because UI Type it works with is already known to CRUD Editor. When omitted for Custom FieldInputComponent, UI Type is considered to be unknown. In such a case- either define converter,
- or unconverted (i.e. of Field Type) field value is sent to FieldInputComponent and FieldInputComponent is presupposed to return a value of Field Type.
render.value.type
is ignored when customrender.value.converter
is defined. -
render.value.converter
is a custom converter which overwrites default converter, if any. There is a default converter when Field Type is known to CRUID Editor and- component is Embedded FieldInputComponent, or
- component is Custom FieldInputComponent and
render.value.type
with UI Type is specified.
-
render.value.converter.parse
must throw an error if a value is invalid, i.e. cannot be converted to the Field Type.
modelDefinition.ui.search().resultFields
An optional array of objects describing which fields should be displayed in Search Result listing. Each object from the array
- either references Persistent Field name defined in model.fields,
- or defines Composite Field name.
By default, all model.fields are used.
?resultFields: [{
name: <string, persistent or composite field name>,
?sortable: <boolean, false by default>,
?sortByDefault: <boolean, false by default>,
?textAlignment: <"left"|"center"|"right">,
?component: <FieldRenderComponent>
}, ...]
Only one field may have sortByDefault: true
.
FieldRenderComponent is a React component for rendering Formatted Instance's field value in Search Result listing.
Props:
Name | Type | Necessity | Default | Description |
---|---|---|---|---|
name | string | mandatory | - | Field name from the resultFields array. |
instance | object | mandatory | - | Entity instance. |
modelDefinition.ui.spinner
An optional React component to be displayed instead of built-in spinner.
Model Definition deep structure:
{
model: {
name: <string, usually singular entity name>,
/*
* Persistent fields CRUD Editor is interested in.
*/
fields: {
<field name>: {
/*
* At least one field must have "unique" property set to true.
*/
?unique: <boolean, whether the field is a part of Logical Key, false by default>,
?type: <string, field type (see corresponding "Terminology" section)>,
/*
* Constraints for field validation.
* Their allowed set and tuning parameters of each constraint depend on field type.
* Constraints are usually called after field input's "onBlur" event
* and before saving instance modifications.
*/
?constraints: {
?max: <number|date, max length for strings or max value for dates/numbers>,
?min: <number|date, min length for strings or min value for dates/numbers>,
?required: <boolean, whether the field value can be empty>,
?email: <boolean>,
?matches: <regexp>,
?url: <boolean>,
/*
* Custom field-validator returning boolean true in case of successful validation,
* or throwing an array of errors (or single error object) if validation failed.
*/
?validate(<serializable, field value>, <object, entity instance>) {
...
throw [<Field Validation Error>, ...];
...
return true;
}
}
},
...
},
/*
* Custom instance-validator, usually called after "Submit" button press
* but before sending the instance to the server for save/modify.
* Field-validation is done upon all fields just before calling the instance-validator.
* The function returns boolean true in case of successful validation,
* or throws an array of error (or single error object) if validation failed.
* The function may also be asyncronous and return a promise.
*/
?validate({
persistentInstnace: <object, entity instance as saved on server, null for Create View>,
formInstnace: <object, entity instance as displayed in the View>,
viewName: <string, View name>, // See EditorComponent props.view.name
}) {
...
throw [<Instance Validation Error>, ...];
...
return true;
},
translations: <object, i18n translations> // See "i18n tranlations" section.
},
permissions: {
crudOperations: {
?create: <boolean, false by default>,
?edit: <boolean, false by default>,
?delete: <boolean, false by default>,
?view: <boolean, false by default>
}
},
/*
* Methods for async operations.
* Each method returns a promise. In case of failure it rejects to
* {
* code: <whole number, error code>,
* ?payload: <any, structure is defined by error code>
* }
*/
api: {
/*
* get single entity instance by its Logical Key.
*/
async get: function({
instance: <object, an entity instance with at least Logical Key fields>
}) {
...
return {
<field name>: <serializable, field value>,
...
};
},
/*
* search for entity instances by a criteria.
*/
async search: function({
?filter: {
<field name>: <serializable, filter value for the field>,
...
},
?sort: <string, sort field name>,
?order: <"asc"|"desc", sort order>,
?max: <natural number, search result limit>,
?offset: <whole number, search result offset>
}) {
...
return {
instances: [{
<field name>: <serializable, field value>,
...
}, ...],
totalCount: <whole number, total number of filtered entity instances>
};
},
/*
* delete entity instances transactionally by their Logical Keys.
*/
async delete: function({
instances: <array[object], entity instances with at least Logical Key fields>
}) {
return {
count: <whole number, how many entity instances where actually deleted>
};
},
/*
* create new entity instance and return its actial server copy.
*/
async create: function({
instance: {
<field name>: <serializable, field value>,
...
}
}) {
...
return {
<field name>: <serializable, field value>,
...
};
},
/*
* update existing entity instance and return its actial server copy.
*/
async update: function({
instance: {
<field name>: <serializable, field value>,
...
}
}) {
...
return {
<field name>: <serializable, field value>,
...
};
}
},
?ui: {
?Spinner: <function, React component to be displayed instead of built-in spinner>,
?search: function() {
...
return {
/*
* Only Persistent fields from model.fields are allowed.
* By default, all Persistent fields from model.fields
* are used for building search criteria.
*/
?searchableFields: [{
name: <string, persistent field name>,
/*
* There is no default "render" property for a field of custom Field Type
* => "render" property must be explicitly defined in such a case.
*
* Default "render" property for a field of standard Field Type:
* {
* component: <string, id of default FieldInputComponent for displaying the Field Type>,
*
* value: {
* propName: "value",
* type: <string, UI Type peculiar to the default FieldInputComponent>
* }
* }
*/
?render: {
/*
* Either custom FieldInputComponent (see corresponding subheading)
* or id of embedded FieldInputComponent.
*/
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of component prop with field value>,
/*
* Redundant for an embedded FieldInputComponent,
* because UI Type it works with is already known to CRUD Editor.
*
* When omitted for custom FieldInputComponent, UI Type is considered to be unknown.
* In such a case:
* 1. either define converter,
* 2. or unconverted (i.e. of Field Type) field value is sent to FieldInputComponent and
* FieldInputComponent is presupposed to return a value of Field Type.
*
* Ignored when custom "converter" is defined.
*/
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
/*
* Custom converter which overwrites default converter, if any.
*
* There is a default converter when Field Type is known to CRUID Editor and
* 1. component is embedded FieldInputComponent, or
* 2. component is custom FieldInputComponent and "type" with UI Type is specified.
*/
?converter: {
/*
* Field Type to UI Typer converter.
*/
format(value) {
...
return <serializable>;
}
/*
* UI Type to Field Type converter.
* An error must be thrown if a value is invalid, i.e. cannot be converted to the Field Type.
*/
parse(value) {
...
return <serializable>;
}
}
}
}
}, ...],
/*
* Both persistent and composite fields are allowed.
* By default, all Persistent fields from model.fields are used in result listing.
* Only one field may have "sortByDefault" set to true.
*/
?resultFields: [{
name: <string, persistent or composite field name>,
?sortable: <boolean, false by default>,
?sortByDefault: <boolean, false by default>,
?textAlignment: <"left"|"center"|"right">,
?component: <FieldRenderComponent> // see "FieldRenderComponent" subheading.
}, ...],
/*
* Configuration for Standard Operations (see corresponding Terminology section).
* NOTE: only "delete" can be configured now.
*/
?standardOperations: {
<name, stadard operation ID>: <object, entity instance> => {
...
return {
?disabled: <boolean, false by default>
};
},
...
}
};
},
/*
* Generate label for entity instance description.
* Default is instance._objectLabel
*/
?instanceLabel(<object, entity instance>) {
...
return <string, entity instance description>;
},
?create: {
/*
* Generate and return an entity instance with predefined field values.
* The instance is not persistent.
*/
?defaultNewInstance: function(<object, "search" View State>) {
...
return <object, entity instance>;
},
/*
* tab(), section() and field() may be replaced with false/undefined/null which are ignored.
*
* See "TabFormComponent" and "FieldInputComponent" subheading for React components props.
*
* If formLayout is not specified, create/edit/show View does not have any tabs/sections
* and displays all fields from the model. The following fields are read-only in such case:
* -- all fields in Show view,
* -- Logical Key fields in Edit view.
*/
?formLayout: ({ tab, section, field }) => instance => {
...
return [
?tab(
{
name: <string, tab name>,
?disabled: <boolean, false by default>,
?component: <function, TabFormComponent>,
?columns: <number, 1 by default>
},
?section(
{ name: <string, section name>, ?columns: <number, columns in parent tab by default> },
?field({
name: <string, field name>,
?readOnly: <boolean, false by default>,
?render: { // see "searchableFields" above for detailed explanation.
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of component prop with field value, "value" by default>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: { format, parse }
}
},
?validate(<serializable, field value>, <object, entity instance>) { // Field-validator.
...
throw [<Instance Validation Error>, ...];
...
return true;
}
}),
?field({
name: <string, field name>,
?readOnly: <boolean, false by default>,
?render: { // see "searchableFields" above for detailed explanation.
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of Component prop with field value, "value" by default>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: { format, parse }
},
?validate(<serializable, field value>, <object, entity instance>) { // Field-validator.
...
throw [<Instance Validation Error>, ...];
...
return true;
}
}
}),
...
),
?field({
name: <string, field name>,
?readOnly: <boolean, false by default>,
?render: { // see "searchableFields" above for detailed explanation.
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of Component prop with field value, "value" by default>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: { format, parse }
}
},
?validate(<serializable, field value>, <object, entity instance>) { // Field-validator.
...
throw [<Instance Validation Error>, ...];
...
return true;
}
}),
...
)
?section({ name: <string, section name> },
?field({
name: <string, field name>,
?readOnly: <boolean, false by default>,
?render: { // see "searchableFields" above for detailed explanation.
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of Component prop with field value, "value" by default>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: { format, parse }
}
}
?validate(<serializable, field value>, <object, entity instance>) { // Field-validator.
...
throw [<Instance Validation Error>, ...];
...
return true;
}
}),
...
),
?field({
name: <string, field name>,
?readOnly: <boolean, false by default>,
?render: { // see "searchableFields" above for detailed explanation.
component: <FieldInputComponent|string>,
?props: <object, the component props to overwrite defaults>,
?value: {
?propName: <string, a name of Component prop with field value, "value" by default>,
?type: <string, embedded UI Type (see corresponding "Terminology" section)>,
?converter: { format, parse }
}
}
?validate(<serializable, field value>, <object, entity instance>) { // Field-validator.
...
throw [<Instance Validation Error>, ...];
...
return true;
}
}),
...
]
},
/*
* Configuration for Standard Operations (see corresponding Terminology section).
* NOTE: nothing can be configured now.
*/
?standardOperations: {
<name, stadard operation ID>: <object, entity instance> => {
...
return {
?disabled: <boolean, false by default>
};
},
...
}
},
?edit: {
?formLayout: <function> // see ui.create.formLayout for details
/*
* Configuration for Standard Operations (see corresponding Terminology section).
* NOTE: only "delete" can be configured now.
*/
?standardOperations: {
<name, stadard operation ID>: <object, entity instance> => {
...
return {
?disabled: <boolean, false by default>
};
},
...
}
},
?show: {
?formLayout: <function> // see ui.create.formLayout for details
/*
* Configuration for Standard Operations (see corresponding Terminology section).
* NOTE: nothing can be configured now.
*/
?standardOperations: {
<name, stadard operation ID>: <object, entity instance> => {
...
return {
?disabled: <boolean, false by default>
};
},
...
}
},
/*
* Views in addition to standard ones.
* TODO
*/
?customViews: {
<view name>: <ViewComponent>, // see "ViewComponent" subheading.
...
},
/*
* Custom operations available in CRUD Editor.
* No arguments are passed to the method in Create View
* since it does not have persistent instance.
*/
?customOperations: function(<object, entity persistent instance> ) {
...
return [{
/*
* handler() is called at operation button render, not after button press
* => handler() must be a pure function.
* If handler() returns undefined, the button is displayed as disabled;
* otherwise view's name/state are saved and get redirected to only after the button press.
* When the button gets pressed and there are unsaved changes, Confirmation Dialog is called.
*
* Disabling the button by appropriate ui() return value
* prevents handler from been called at operation button render.
*/
handler() {
...
// return value is either undefined or view name/state.
return {
name: <string, View Name>,
?state: <object, View State, empty object by default>
};
},
ui({
name: <string, View name>, // See EditorComponent props.view.name
state: <object, Full View State> // See EditorComponent props.view.state
}) {
return {
title() {
...
return <string, custom operation translated title>,
},
?show: <boolean, true by default>,
?disabled: <boolean, false by default>,
/*
* whether the operation has own dedicated button (false)
* or it is to be placed in a dropdown of a previous button (true).
* A previous button is either previous custom operation with "dropdown" set to false
* OR (for Search View) "Edit" button if there is no such custom operation.
*/
?dropdown: <boolean, true by default>,
/*
* React Element or string name of an icon to be displayed inside a button, ex. "trash", "edit";
* see full list at
* http://getbootstrap.com/components/#glyphicons
*/
?icon: <string|element>
};
}
}, ...]
}
}
}
Custom React Component for rendering Formatted Instance's field in Search Form or Create/Edit/Show Form.
Props:
Name | Type | Necessity | Default | Description |
---|---|---|---|---|
readOnly | boolean | optional | false | Whether field value can be changed |
value | serializable | mandatory | - | [[Persistent field |
onChange | function | mandatory | - | Handler called when component's value changes.
|
onBlur | function | optional | - | Handler called when component loses focus.
|
In CRUD Editor here are two embedded FieldInputComponents:
FieldInputComponent | id |
---|---|
BUILTIN_INPUT | "input" |
BUILTIN_RANGE_INPUT | "rangeInput" |
For being treated as embedded, string id must be used. Additionally, the embedded FieldInputComponents can be imported from CRUD Editor package:
import { BUILTIN_INPUT, BUILTIN_RANGE_INPUT } from '@opuscapita/react-crudeditor';
Embedded FieldInputComponents also accept all props defined for FieldInputComponent.
Singular input field.
props.type | Description | UI Type | Auto-convertable field types |
---|---|---|---|
string |
Regular input field which works with strings | UI_TYPE_STRING | FIELD_TYPE_STRING, FIELD_TYPE_BOOLEAN, FIELD_TYPE_DECIMAL, FIELD_TYPE_INTEGER, FIELD_TYPE_STRING_DATE, FIELD_TYPE_STRING_DECIMAL, FIELD_TYPE_STRING_INTEGER |
checkbox |
Checkbox | UI_TYPE_BOOLEAN | FIELD_TYPE_BOOLEAN |
date |
DateInput | UI_TYPE_DATE | FIELD_TYPE_STRING_DATE |
integer |
Input which accepts only numbers and - sign and formats using i18n.formatNumber |
UI_TYPE_INTEGER | FIELD_TYPE_STRING_INTEGER, FIELD_TYPE_INTEGER, FIELD_TYPE_BOOLEAN, FIELD_TYPE_STRING |
decimal |
Input which accepts only numbers and - sign and formats using i18n.formatDecimalNumber |
UI_TYPE_DECIMAL | FIELD_TYPE_STRING_DECIMAL, FIELD_TYPE_DECIMAL, FIELD_TYPE_BOOLEAN, FIELD_TYPE_STRING |
Range input field.
props.type | Description | UI Type | Auto-convertable field types |
---|---|---|---|
string |
Range input which works with strings | UI_TYPE_STRING_RANGE_OBJECT | FIELD_TYPE_DECIMAL_RANGE, FIELD_TYPE_INTEGER_RANGE, FIELD_TYPE_STRING_DATE_RANGE, FIELD_TYPE_STRING_DECIMAL_RANGE, FIELD_TYPE_STRING_INTEGER_RANGE |
date |
DateRangeInput | UI_TYPE_DATE_RANGE_OBJECT | FIELD_TYPE_STRING_DATE_RANGE |
integer |
Range input which accepts only numbers and - sign and formats using i18n.formatNumber |
UI_TYPE_INTEGER_RANGE_OBJECT | FIELD_TYPE_STRING_INTEGER_RANGE, FIELD_TYPE_INTEGER_RANGE |
decimal |
Range input which accepts only numbers and - sign and formats using i18n.formatDecimalNumber |
UI_TYPE_DECIMAL_RANGE_OBJECT | FIELD_TYPE_STRING_DECIMAL_RANGE, FIELD_TYPE_DECIMAL_RANGE |
If you define just a Field Type in Model Definition's model.fields.<field name>.type (and omit any custom render in searchableFields and formLayout), the following components will be default for the fields:
Field Type | Component | props.type |
---|---|---|
FIELD_TYPE_BOOLEAN | BUILTIN_INPUT | 'checkbox' |
FIELD_TYPE_STRING | BUILTIN_INPUT | 'string' |
FIELD_TYPE_DECIMAL_RANGE | BUILTIN_RANGE_INPUT | 'decimal' |
FIELD_TYPE_INTEGER_RANGE | BUILTIN_RANGE_INPUT | 'integer' |
FIELD_TYPE_STRING_DATE_RANGE | BUILTIN_RANGE_INPUT | 'date' |
FIELD_TYPE_STRING_DECIMAL_RANGE | BUILTIN_RANGE_INPUT | 'string' |
FIELD_TYPE_STRING_INTEGER_RANGE | BUILTIN_RANGE_INPUT | 'string' |
Field Type | Component | props.type |
---|---|---|
FIELD_TYPE_DECIMAL | BUILTIN_INPUT | 'decimal' |
FIELD_TYPE_INTEGER | BUILTIN_INPUT | 'integer' |
FIELD_TYPE_STRING_DATE | BUILTIN_INPUT | 'date' |
FIELD_TYPE_STRING_DECIMAL | BUILTIN_INPUT | 'string' |
FIELD_TYPE_STRING_INTEGER | BUILTIN_INPUT | 'string' |
Field Type | Component | props.type |
---|---|---|
FIELD_TYPE_DECIMAL | BUILTIN_RANGE_INPUT | 'decimal' |
FIELD_TYPE_INTEGER | BUILTIN_RANGE_INPUT | 'integer' |
FIELD_TYPE_STRING_DATE | BUILTIN_RANGE_INPUT | 'date' |
FIELD_TYPE_STRING_DECIMAL | BUILTIN_RANGE_INPUT | 'string' |
FIELD_TYPE_STRING_INTEGER | BUILTIN_RANGE_INPUT | 'string' |
Custom React component for rendering Formated Instance's persistent/composite field value in Search Result listing.
Props:
Name | Type | Necessity | Default | Description |
---|---|---|---|---|
name | string | mandatory | - | Field name from Model Definition's ui.search().resultFields |
instance | object | mandatory | - | Entity instance |
React component for a custom rendering of Tab form in create/edit/show Views.
Props:
Name | Type | Necessity | Default | Description |
---|---|---|---|---|
viewName | string | mandatory | - | [[View Name |
instance | object | mandatory | - | persistent instance |
doTransition | function | optional | - | Editor State change handler |
React component for a custom View.
Props:
Name | Type | Necessity | Default | Description |
---|---|---|---|---|
viewState | object | mandatory | - | Custom [[View State |
doTransition | function | optional | - | Editor State change handler |
This handler is called when
- active View changes its State, name argument is optional in such case;
- another View must be displayed, state argument is optional in such case.
function ({
?name: <string, View Name>,
?state: <object, View State>
}) {
...
return; // return value is ignored.
}
Arguments:
Name | Default | Description |
---|---|---|
name | active View Name | To-be-displayed [[View Name |
state | {} |
Full/sliced to-be-displayed [[View State |
If View State is sliced, not given or {}
, all not-mentioned properties retain their current values (or default values in case of initial View rendering).
Model Definition's model.translations object has translations for labels/messages defined in the model. Its shape should correspond to preferred format for @opuscapita/i18n library.
Translation keys convention:
Translation Target | Translation Key | Default translation |
---|---|---|
Model name (shown in the header) | "model.name" |
"model.name" |
Model tab label | "model.tab.<tab name>.label" |
titleCase("<tab name>") |
Model section label | "model.section.<section name>.label" |
titleCase("<section name>") |
Model field label | "model.field.<field name>.label" |
titleCase("<field name>") |
Model field hint | "model.field.<field name>.hint" |
- |
Model field tooltip | "model.field.<field name>.tooltip" |
- |
Custom Field Validation Error | "model.field.<field name>.error.<error id>" |
error.message || error.id |
Instance Validation Error | "model.error.<error id>" |
error.message || <built-in error message> |
titleCase() converts its arugment from camelcase to titlecase, ex. titleCase("maxOrderValue") === "Max Order Value"
.
React context must have i18n
property with I18nManager as its value.