Using MANY datatype in UB application. #
Imagine that we want to add to our request information about the region of the city to which that request related for.
Since one request can relate to several regions of the city, we need to have the ability of multiple choice.
For this, we need the Many
datatype.
Let's look at how to use it.
Creating Many datatype attribute #
First, we need to create the entity that represents the city region.
req_cityRegion.meta
:
{
"caption": "City region",
"description": "city region",
"descriptionAttribute": "name",
"attributes": [
{
"name": "name",
"dataType": "String",
"size": 255,
"caption": "Region name",
"description": "Region name",
"allowNull": false,
"isMultiLang": false,
"isUnique": true
}
],
"mixins": {
"mStorage": {}
}
}
Then, in the req_reqList
entity add an attribute of the datatype Many
that is associated with the req_cityRegion
entity:
{
"name":"regionList",
"dataType": "Many",
"associatedEntity": "req_cityRegion",
"associationManyData": "req_city_region_map",
"caption": "List city regions",
"description": "List of city regions",
"allowNull": true
}
After running the generateDDL, the req_cityRegion_map
table will be created with two fields - sourceID(bigint)
and destID(bigint)
.
The sourceID
is an ID of the req_reqList
table and the destID
is an ID of the req_cityRegion
table.
Now, we will add the script for filling the req_cityRegion
table.
_initialData/040_fill_cityRegions.js
:
module.exports = function (session) {
const path = require('path')
const fs = require('fs')
const { dataLoader, csv, argv } = require('@unitybase/base')
const conn = session.connection
const fn = path.join(__dirname, '/req_cityRegions.csv')
let fContent = fs.readFileSync(fn)
if (!fContent) {
throw new Error(`File ${fn} is empty or not exist`)
}
fContent = fContent.toString('utf8').trim()
const csvData = csv.parse(fContent)
// check existing records in the DB
const notExisted = csvData.filter(
(row) => !conn.lookup('req_cityRegion', 'ID',
conn.Repository('req_cityRegion').where('name', '=', row[0]).ubql().whereList
)
)
console.info('\t\tFill City Region field (req_cityRegion)')
dataLoader.loadArrayData(conn, notExisted, 'req_cityRegion', 'name'.split(';'), [0], 1)
}
Don't forget to put these regions names to _initialData/req_cityRegions.csv
:
central
southern
northern
west
eastern
We also need a shortcut for the City Region.
We will create this with _initalData/010_create_navshortcuts.js
.
Add the following code to it:
lastID = conn.lookup('ubm_navshortcut', 'ID', {
expression: 'code',
condition: 'equal',
values: { code: 'req_cityRegion' }
})
if (!lastID) {
console.log('\t\tcreate `City regions` shortcut')
lastID = conn.insert({
fieldList: ['ID'],
entity: 'ubm_navshortcut',
execParams: {
desktopID: desktopID,
code: 'req_cityRegion',
caption: 'City region',
iconCls: 'fa fa-braille',
displayOrder: 20,
cmdCode: JSON.stringify({
cmdType: 'showList',
cmdData: { params: [{ entity: 'req_cityRegion', method: 'select', fieldList: '*' }] }
}, null, '\t')
}
})
} else {
console.info('\t\tuse existed shortcut with code `req_cityRegion`', lastID)
}
Run generateDDL and initialize commands or init
script from Getting Started part of this tutorial.
And the last step - add a new field to the req_reqList-fm.def
:
{ attributeName: "regionList" /*Regions name*/}
Now, we can make the multiple select for the list of city regions:
SELECT to the Many attribute #
Let's consider an example of a SELECT for Many
datatype attribute.
We need to add a button to the toolbar to the list of applications, by clicking on which we can see the number of requests for the selected region.
For adding a button change the req_reqList
entity shortcut command code to the following:
{
"cmdType": "showList",
"cmdData": {
"params": [{
"entity": "req_reqList",
"method": "select",
"fieldList": "*"
}]
},
"customActions": [{
"actionText": "Regions requests",
"glyph": 62113,
"text": "Regions requests",
"handler": function(cmp) {
var config = {
cmdType: 'showForm',
method: 'select',
formCode: 'req_cityRegion-select',
entity: 'req_cityRegion'
}
UB.core.UBApp.doCommand(config)
}
}]
}
NOTE
❗ The syntax checker for source code can produce errors. You can ignore them.
As we see, in the toolbar for the list of requests, a button has appeared:
By clicking on this button the req_cityRegion-select
form must appear.
So, let's create this form first:
NOTE
❗ In the Model
field use the name of the directory that you have created in models
directory(models/_your_module_name_
).
with the following code in Interface's definition
section:
exports.formDef = 'request.selectRegion'
Ext.define('request.selectRegion', {
extend: 'Ext.form.Panel',
size: {
width: 500,
height: 600
},
items: [{
xtype: 'ubcombobox',
width: 400,
name: 'cbxRegion',
fieldLabel: UB.i18n('City region'),
allowBlank: false,
ubRequest: {
entity: 'req_cityRegion',
method: 'select',
fieldList: ['ID', 'name']
}
}],
buttons: [{
ubID: 'btnOK',
text: UB.i18n('ok'),
iconCls: 'fa fa-save',
formBind: true
}, {
ubID: 'btnCancel',
text: UB.i18n('cancel'),
iconCls: 'fa fa-times'
}],
initComponent: function() {
let me = this
me.callParent(arguments)
}
})
Now we can press on button that we have created and see the following:
To finish our task, we should add two buttons to our form.
The Ok
button that will use regions selected in the field to find the number of requests associated with them.
And the Cancel
button that just closes the form.
Add the following code to the initComponent
function:
me.down('button[ubID="btnOK"]').handler = function() {
let region = [];
region[0] = me.getForm().findField('cbxRegion').getValue()
let regionName = me.getForm().findField('cbxRegion').findRecordByValue(region[0]).get('name');
let requestInRegion = UB.Repository('req_reqList').attrs(['ID', 'regionList']).where('regionList', '=', region).selectAsObject()
.then(function(result) {
if (result.length) {
$App.dialogInfo('Number of requests for the district: ' + regionName + ' - ' + result.length);
} else {
$App.dialogInfo('There are any requests for the district: ' + regionName);
}
})
}
me.down('button[ubID="btnCancel"]').handler = function() {
me.up('window').close()
}
NOTE
❗ In order to search for regions associated with requests, the query SELECT is made not to the req_cityRegion_map
table in the DB,
but to the original req_reqList
entity that contains the regionList
attribute.
The result of our work: