Using MANY datatype in UB application.

The attributes of MANY datatype have some specificity. Consider an example that demonstrates the use of this type of data attribute.
Let the request on the portal contain information about the region of the city to which it refers.
One request can relate to several regions of the city, so you need to give the user a multiple choice.

Creating Many datatype attribute

Create the entity of the city regions - req_cityRegion.meta


{
 "caption": "City region",
 "description": "city region",
 "descriptionAttribute": "name",
 "attributes": {
   "name": {
     "dataType": "String",
     "size": 255,
     "caption": "Region name",
     "description": "Region name",
     "allowNull": false,
     "isMultiLang": false,
     "isUnique": true
   }
 },
 "mixins": {
   // the mandatory section (can be empty)
   "mStorage": {
   }
 }
}

In entity req_reqList (req_reqList.meta) will create an attribute of the datatype many that is associated with the entity req_cityRegion

{
 "name":"regionList",
 "dataType": "Many",
 "associatedEntity": "req_cityRegion",
 "associationManyData": "req_cityRegion_map",
 "caption": "List city regions",
 "description": "List of city regions",
 "allowNull": true
}

After running the generateDDL script in the database, a req_cityRegion_map table will be created with the sourceID(bigint) and destID(bigint) fields, where the sourceID - ID of the req_reqList table, the destID - ID of the req_cityRegion table. Create the script to fill the req_cityRegion table data.
_initialData/040_fill_cityRegions.js

module.exports = function(session){
 const path = require('path')
 const fs = require('fs')
 const {dataLoader, csv, argv} = require('@unitybase/base')
 let  conn = session.connection;
 let 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.trim()
 let csvData = csv.parse(fContent)
 //check existing records in the DB
 let 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);

};

Regions name in _initialData/req_cityRegions.csv

central  
southern  
northern  
west  
eastern  

Add City Region shortcut in _initalData/010_create_navshortcuts.js

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')
   }
 });
}

Run the generateDDL and initialize scripts or init.cmd.

Add a new field to the req_reqList-fm.def form

 { attributeName: "regionList" /*Regions name*/}

reqListForm

This field has the multiple select type.

SELECT to the Many attribute

Let's consider an example of a SELECT to many datatype attribute.
Add a button to the toolbar to the list of applications, by clicking on which you can see the number of requests for the selected region.

Adding a button to the entitygrid panel

Change the req_reqList shortcut source 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)
     
    }
  }]
}

In the toolbar of the list of requests, a button will appear

regionListButton

By clicking on this button the req_cityRegion-select form should open.
Create this form in the application

cityRegionForm

With the code

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'),
    glyph: UB.core.UBUtil.glyphs.faSave,
    formBind: true
  }, {
    ubID: 'btnCancel',
    text: UB.i18n('cancel'),
    glyph: UB.core.UBUtil.glyphs.faTimes
  }],

  initComponent: function() {
    let me = this
    me.callParent(arguments)
}})

View of form

cityRegionFormView

Add an event to the OK button that will read the region selected in the field and search for it in the list of regions associated with the requests.

Add this 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);
          }
        })

    }

And closing the form by clicking CANCEL button

me.down('button[ubID="btnCancel"]').handler = function() {
      me.up('window').close()
    }

! Note that in order to search for regions associated with requests, the condition where must be an array and the query SELECT is made not to the req_cityRegion_map table in DB, but to the original entity req_reqList that contains the attribute regionList

As result of the script execution should be an information window that indicates how many requests there are for the selected region

selectResult

Next step