Fields
A field describes a property of a DataElement. These fields will be expanded to columns in a database table and fields in forms and are the basic content of a DataElement.
<dataElement name="Starship">
<fields>
<field name="field1"/>
<field name="field2"/>
</fields>
</dataElement>
Fields can either be ValueFields (basic attributes) or LinkFields (references to other DataElements).
ValueFields
ValueFields are simple fields that have a name and a valueFieldType. The ValueFieldType defines how the field is
stored and represented.
E.g. the following field will be represented and stored as a simple String:
<field name="address">
<fieldType>VALUE_FIELD</fieldType>
<valueField>
<valueFieldType component="" name="String"/>
</valueField>
</field>
There are several built-in ValueFieldTypes, but it also possible to define a ValueFieldType yourself.
Initial Values
FieldProvides a default value for a ValueField that has a boolean, numeric or string type. The value is assigned as default in the data layer and also as the initial value in forms in the Knockout UI.
In case of a string, the value must be surrounded with quotes.
- Boolean:
defaultValue: true. Setstrueas the initial value for a Boolean field. - Number:
defaultValue: 5. Sets5as the initial value for a number (Integer, Long, Double...) field. - String:
defaultValue: 'new name'. Setsnew nameas initial value for a String field.
<options>
<defaultValue>'New Value'</defaultValue>
</options>
FieldCauses a new UUID to be generated and stored in this field whenever a new instance is created. Use value "if_empty" to generate a UUID only if no value was passed to the create method in the details object.
<options>
<generateUuid/>
</options>
<options>
<generateUuid>if_empty</generateUuid>
</options>
LinkFields
LinkFields provide ways to link to another DataElement. They have a name, a targetElement and a linkFieldType.
The target element is a reference to another DataElement. E.g. if you wish to link to an 'Employee' DataElement
<field name="employee">
<fieldType>LINK_FIELD</fieldType>
<linkField>
<targetElement component="administration" name="Employee"/>
<linkFieldType name="Ln01"/>
</linkField>
</field>
The LinkFieldType defines the multiplicity of the relationship.
There are 6 Link Field Types:
- Ln01: many-to-one, code-managed
- Ln02: many-to-one, JPA-managed
- Ln03: many-to-many, JPA-managed, owning side
- Ln04: one-to-many, JPA-managed
- Ln05: one-to-many, code-managed
- Ln06: many-to-many, JPA-managed, other side
Code-managed vs JPA-managed
When selecting a Link Field Type, you can choose between code-managed (Ln01 and Ln05) or JPA-managed (Ln02 and Ln04).
- Code-managed links will be generated as
Longvalues in the Data layer. The generated code will then resolve the links through lookups. Code-managed links work for links between Components, since they do not require the tables to be in the same database or schema. - JPA-managed links are generated as references to JPA objects. The resolving is provided by the JPA implementation. JPA-managed links only work within Components, since other Components can have different schema's or databases.
Reverse Links
If you have a many-to-one link, you may want a one-to-many link in the other direction. There are some requirements to get this to work:
- The links should both be either code-managed (Ln01 and Ln05) or JPA-managed (Ln02 and Ln04).
- The many-to-one side (Ln01 or Ln02), should be named after the target DataElement (with first letter lowercase).
- The DataElement on the many side should also have a Finder defined, called
findBy{element}Eq, where{element}is the field on the one side.
Ln04 and Ln05 links need a reverse link to work.
Many-to-many Links
If you have an Ln03 (many-to-many) link and wish to add the reverse link, you can add an Ln06 link on the other Data Element. In this case, the name of the Ln03 field needs to be identical to the name of the element where the corresponding Ln06 link is specified, followed by the character “s”
One-to-one Links
There is currently no support for one-to-one links. The best option is to use Ln01 or Ln02 on one side.
Fields with specific behaviours
Some field names have specific behaviour. Creating a field with that name will also activate the corresponding feature.
Name
If a DataElement has a field name, it should be a String. The name field is part of the DataRef for the DataElement,
meaning it can be used to identify an instance of that DataElement.
The name will also be used as a default representation in dropdowns.
If no name field is defined, an implicit name field will still be expanded, but the value of the name itself will be auto-generated.
It is possible to prevent this behaviour with the option nameNotWanted, but be aware that this has far-reaching effects, as the option itself is a combinatorial effect.
Audit fields
Create/modify timestamps
The options audit.create.timestamp and audit.modify.timestamp can be used to track creation and modification
timestamps of instances of a DataElement. These are set in the data layer right before saving the instance to the
database.
FieldA field of type Date or Timestamp marked with this option will have the current timestamp stored in it when an
an instance of the element is created.
This option is implicitly added to a field with name enteredAt if it is not explicitly defined on any other field in
the DataElement.
<options>
<audit.create.timestamp/>
</options>
FieldA field of type Date or Timestamp marked with this option will have the current timestamp stored in it when an
an instance of the element is modified. The timestamp is also stored when the instance is created as we consider this to
also be the first modification event in the scope of this functionality.
This option is implicitly added to a field with name lastModifiedAt if it is not explicitly defined on any other field
in the DataElement.
<options>
<audit.modify.timestamp/>
</options>
Create/modify author
The options audit.create.author and audit.modify.author can be used to track who creates and modifies instances of a
DataElement. This is achieved using references to the account::User element based on the contents of the active
UserContext context group. These are set in the data layer right before saving the instance to the database. If no
UserContext is present or no valid user data is stored within, the relevant field will be set to an empty value.
It may be possible to use this for links to elements other than account::User, as the implementation supports Ln02
links as well as uses a generic DataRef object constructed out of the information in UserContext, but this is not
a recommended use-case!
FieldA link field of type Ln01 to account::User marked with this option will have a reference to the user in the
UserContext stored in it when an instance of the element is created.
This option is implicitly added to a field with name enteredBy if it is not explicitly defined on any other field in
the DataElement.
<options>
<audit.create.author/>
</options>
FieldA link field of type Ln01 to account::User marked with this option will have a reference to the user in the
UserContext stored in it when an instance of the element is modified. The reference is also stored when the instance
is created as we consider this to also be the first modification event in the scope of this functionality.
This option is implicitly added to a field with name lastModifiedBy if it is not explicitly defined on any other field
in the DataElement.
<options>
<audit.modify.author/>
</options>
Fields called enteredBy or lastModifiedBy should be Ln01 LinkFields to account::User.
They will be automatically updated to the user that created (enteredAt) or last modified (lastModifiedAt) an instance.
Disabled
If a DataElement has a field disabled, it should be a String.
The field will be used to 'soft delete' instances, meaning that instances will have disabled set to yes when deleted, rather than be deleted from the table.
Soft deleted instances will be filtered out when executing finds.
It is also possible to use another field for this functionality by adding the cruds.softDelete option.