Create new entity with together with related entities
Level: Intermediate
Keywords: business action, create feature, related features, stepper
The result: definition of action and input form needed to create new feature instance together with other contextual data (e.g. related features)
How to create a new instance of the feature together with other contextual data?​
This example describes a case when together with creating of new instance of feature it is necessary to create other cotextual data, e.g. some elements related with just created feature instance. Creating of new entity in this example is activated by means of + icon from samo-browse and for filling data samo-stepper module is used.

Fig. 1. Icon + from samo-browse runs action form for creating new entity with other data context
Create Action form​
The definition of Action form is contained in the file /dynamic-client/samo-entities/entities/detail/ft_personActionDetail.json. In this case samo-stepper module is used for dividing inputs (forms) to two steps and samo-grid-form for arranging data items. Except for attributes that belong to the feature type being created, also data for associated addresses and contacts can be selected inside this action form.
{
"createNewPerson" : {
"title": "Creating new person with addresses and contacts",
"size": "normal",
"sections": [
{
"module":{
"type" : "component:dynamic-app/modules/forms/samo-stepper-module",
"steps": [
{
"title": "Basic person data",
"optional": false,
"sections": [
{
"module": {
"type": "component:dynamic-app/modules/forms/samo-grid-form",
"rows": [
{
"groups": [
{
"elements": [
{
"label": "Name",
"property": "at_person_name",
"type": "text",
"dynamic": true,
"validation": {
"required": true,
"validateOnChange": true,
"errorMessage": "Value is mandatory"
},
"span": {
"m": 5
}
},
{
"label": "Surname",
"property": "at_person_surname",
"dynamic": true,
"type": "text",
"validation": {
"required": true,
"validateOnChange": true,
"errorMessage": "Value is mandatory"
},
"span": {
"m": 5
}
},
{
"label": "Title",
"type": "codelist",
"property": "at_person_cl_title",
"codelist": "cl_title",
"idProperty": "ca_title_id",
"titleProperty": "ca_title_desc",
"defaultSort": [
{
"property": "ca_titul_desc.keyword",
"order": "asc"
}
],
"span": {
"m": 2
}
}
]
}
]
},
{
"groups": [
{
"elements": [
{
"label": "Birthday",
"property": "at_person_birthday",
"type": "date",
"validation": {
"type": "date",
"max": "{today:}",
"required": true,
"validateOnChange": true,
"errorMessage": "Value is mandatory"
},
"span": {
"m": 2
}
},
{
"label": "Type of marital status",
"type": "codelist",
"property": "at_person_cl_maritalStatus",
"codelist": "cl_maritalStatus",
"idProperty": "ca_maritalStatus_id",
"titleProperty": "ca_maritalStatus_description",
"defaultSort": [
{
"property": "ca_maritalStatus_description.keyword",
"order": "asc"
}
],
"span": {
"m": 3
}
}
]
}
]
},
{
"groups": [
{
"elements": [
{
"label": "Note",
"type": "text",
"property": "at_person_note",
"span": {
"m": 12
}
}
]
}
]
}
]
}
}
]
},
{
"title": "Addresses, contacts",
"optional": false,
"sections": [
{
"module": {
"type": "component:dynamic-app/modules/forms/samo-grid-form",
"rows": [
{
"groups": [
{
"elements": [
{
"title": "Addresses",
"type": "entity-modules:entity-list",
"property": "var_addresses",
"entity": ["ft_address"],
"relation": "as_address_person",
"role": "rt_address",
"createNewEntity": true,
"removableEntity" : false,
"editableEntity" : false,
"displayType": "table",
"multiSelectEnabled": false,
"columnSelectDisabled": true,
"span": {
"m": 12
}
},
{
"title": "Contacts",
"type": "entity-modules:entity-list",
"property": "var_contacts",
"entity": ["ft_contact"],
"relation": "as_contact_person",
"role": "rt_contact",
"createNewEntity": true,
"removableEntity" : false,
"editableEntity" : false,
"displayType": "table",
"multiSelectEnabled": false,
"columnSelectDisabled": true,
"span": {
"m": 12
}
}
]
}
]
}
]
}
}
]
}
]
}
}
]
}
}
Addition of a definition inside samo-browse metadata​
If it is required that the creation of a new instance using the Action form will be started from given page i.e. given samo-browse, then definition of samo-browse module must be extended by insertEntities definition. Within this definition using of specific business action is specified. If the Action form has the same name as business action, then it is automatically opened for creating a new entity.
{
"module" : {
"type": "component:entity-modules/browse/samo-browse",
...
"insertEntities": [
{
"entity": "ft_person",
"title" : "Creating new person with addresses and contacts",
"type": "businessAction",
"actionId": "createNewPerson",
"confirmButtonTitle": "CREATE",
"noResultDetail" : true,
"allowContinuousAction": false,
"navigateAfterFinish": {
"page": "pg_persons",
"arguments": {
"detail": "{get:#fullId}"
}
}
}
]
}
}
Registration of the relevant business action​
Bussiness action mus be defined in given entity (feature type) business metadata. The name of action must be the same as name of Action form context.
"actions": {
"createNewPerson": {
"steps": [
{
"type": "script",
"source": "scripts/createNewPerson.js"
}
]
}
}
Creating of business action script​
Bussiness action script (JavaScript) is located and named based on parametr source from relevant action definition.
function action(context) {
api.logging().prepareLog(context).message(scriptFileName).addValue("START").logDebug();
var jsonRequestReader = api.request()
.prepareCreateJSONRequestReader(context)
.create()
var requestContent = jsonRequestReader.getRequestBodyAsObject();
if (requestContent.var_ft_address) {
requestContent.at_person_name = requestContent.var_ft_address[0]["var-at_person_name"];
}
//creating new person
var newPerson = api.features()
.prepareCreateFeature(context)
.entityType("ft_person")
.createBody(requestContent)
.create();
api.logging().prepareLog(context).message(scriptFileName).addVariable("newPerson", newPerson).logDebug();
// creating addresses
if (requestContent.var_ft_address) {
var addresses = requestContent.var_ft_address;
for (var i = 0; i < addresses.length; i++) {
api.features().prepareCreateRelatedFeature(context)
.entityRef(newPerson)
.relatedType("ft_address")
.relation("as_address_person")
.role("rt_address")
.createBody(addresses[i])
.create();
}
api.logging().prepareLog(context).message(scriptFileName).addVariable("address", requestContent.var_ft_address).logDebug();
}
// creating contacts
if (requestContent.var_ft_contact) {
var contacts = requestContent.var_ft_contact;
for (var i = 0; i < contacts.length; i++) {
api.features().prepareCreateRelatedFeature(context)
.entityRef(newPerson)
.relatedType("ft_contact")
.relation("as_contact_person")
.role("rt_contact")
.createBody(contacts[i])
.create();
}
api.logging().prepareLog(context).message(scriptFileName).addVariable("contact", requestContent.var_ft_contact).logDebug();
}
api.logging().prepareLog(context).message(scriptFileName).addValue("END").logDebug();
var jsonResponse = api.response()
.prepareCreateJSONResponse(context)
.responseBody({fullId: newPerson.type + "/" + newPerson.id})
.create();
return api.result()
.prepareCreateActionResult(context)
.result(jsonResponse)
.create();
}