Модель
Для получения данных из БД в Лексеме есть два инструмента:
Модель. Даёт возможность получить одну запись из таблицы и связать ее с элементами управления на форме.
Запрос. Даёт возможность выполнять любой запрос в БД.
В этом занятии начнём изучение модели. Дополним предыдущий пример, сделав выбор товаров и групп из заранее созданного справочников, которые будут храниться в таблицах БД.
Для начала создадим новую форму. Возьмем за основу ControlsForm, скопируйте их содержимое.
ModelDemoForm.js. Заменим ссылку на макет и наименование класса.
| ….
import template from './ModelForm.xml'; // импорт макета документа
….
export default class ModelForm extends Form {
constructor(...args) {
...
|
ModelDemoForm.xml. Заменим только наименование формы.
| <Form writeRoles='super' title='Model Demo'>
<ToolBar>
….
|
И добавим ссылку на форму в меню (units.json).
| ...
},
{
"caption": "Модель",
"key": "ModelDemoForm",
"form": "./forms/ModelDemoForm"
}
...
|
Результат:
Меню.

Форма.

В каталоге проекта models создайте два файла:
Material.model.json
MaterialGroup.model.json
В Material.model.json вставим код «Шаблон Material.model.json»
| {
"dbName": "Material",
"viewName": "",
"typeName": "Material",
"primaryKeyDomain": "Material",
"storeHistory": false,
"primaryKeyProperty": "VCode",
"description": "Справочник товаров",
"properties": {
"VCode": {
"dbName": "VCode",
"type": "bigint"
},
"Name": {
"dbName": "Name",
"type": "string",
"description": "Наименование"
}
},
"details": {},
"rights": {
"create": ["super"],
"read": ["super"],
"update": ["super"],
"delete": ["super"]
}
}
|
В MaterialGroup.model.json вставим:
| {
"dbName": "MaterialGroup",
"viewName": "",
"typeName": "MaterialGroup",
"primaryKeyDomain": "MaterialGroup",
"storeHistory": false,
"primaryKeyProperty": "VCode",
"description": "Справочник групп товаров",
"properties": {
"VCode": {
"dbName": "VCode",
"viewName": "VCode",
"type": "bigint"
},
"Name": {
"dbName": "Name",
"viewName": "Name",
"type": "string",
"description": "Наименование"
}
},
"details": {},
"rights": {
"create": ["super"],
"read": ["super"],
"update": ["super"],
"delete": ["super"]
}
}
|
Обновление БД
Теперь надо создать соответствующие таблицы в БД. В Лексеме есть механизм «Обновление БД», позволяющий упростить эту задачу. Зайдите в новой вкладке браузера на адрес http://localhost:3337/dev#/view/migration.

Нажмите на кнопку «Загрузить». Лексема сравнит описание sql объектов в вашем проекте БД, и в случае расхождения предложит выполнить соответствующий sql-скрипт.

Выделите все строки, нажмите “Выполнить”. Если всё нормально выполнится, то во всех строках в “Статут” будет “Выполнено”.
Результат можно будет увидеть в MS SQL Management Studio (далее MSSMS).

Осталось лишь заполнить эти таблицы. Для этого в MSSMS в данной БД выполните sql скрипты:
Заполнение таблицы:
| declare @VCode int
exec @VCode = dbo.L8_sp_GenCode 'Material', 3
insert into [dbo].[Material] (VCode, Name)
values (@VCode, 'Яблоки')
, (@VCode + 1, 'Апельсины')
, (@VCode + 2, 'Сыр Белебеевский')
|
Чтобы увидеть результат выполните
| SELECT VCode, Name FROM [L84LexPractice].[dbo].[Material]
SELECT VCode, Name FROM [dbo].[MaterialGroup]
|

Аналогично заполним таблицу групп:
| declare @VCode int
exec @VCode = dbo.L8_sp_GenCode 'MaterialGroup', 3
insert into [dbo].[MaterialGroup] (VCode, Name)
values (@VCode, 'Фрукты')
, (@VCode + 1, 'Сыры')
|
| SELECT VCode, Name FROM [dbo].[MaterialGroup]
|

Теперь осталось вывести из на форму.
Для вывода выпадающего списка в Лексеме существует элемент управления Lookup.
Заменим в модели формы ModelForm.xml тип колонки Material, прописав лукап вместо текстового поля:
| <Column text='Группа' datafield='MaterialGroup' width='25%' >
<TextBox />
</Column>
<Column text='Наименование' datafield='Material' width='50%' >
<Lookup dataSource='../models/Material.model.json' showValueMember='false' />
</Column>
|
MaterialGroup оставим также текстовым полем.
Взглянем на форму:

Поля со списками пустые, однако появилась возможность выбора значения из списка. Дело в том, что теперь в этих свойствах хранятся на примитивное значение (в нашем случает текст), в объект. Внесём небольшие изменения в заполняемые при загрузке формы данные:
| get dataGrid() {
return [
{Price: 60.88, Material: { VCode: 1, Name: 'Яблоки' }, MaterialGroup: 'Фрукты' },
{Price: 80, Material: { VCode: 2, Name: 'Апельсины' }, MaterialGroup: 'Фрукты' },
{Price: 170.22, Material: { VCode: 3, Name: 'Сыр Белебеевский' }, MaterialGroup: 'Сыры' }
];
}
|
Результат:

Лукап на форме
Усложним вычисление на кнопке «Calс». Пусть среднее будет считаться только по какой-то конкретной группе товаров. Для этого добавим в макет лукап (“LookupMaterialGroup”), источник данных - модель групп товаров. Добавим ее в группу и немного поменяем свойства других объектов:
| <Group caption='' id='gr4' editorWidth='4' showBorder='false'>
<Button value='Calc' id='ButtonCalc' captionWidth='0' editorWidth='1' width='100%' clicked='ButtonCalc_clicked' />
<Lookup caption='Группа' id='LookupMaterialGroup' dataSource='../models/MaterialGroup.model.json' showValueMember='false' captionWidth='1' editorWidth='2' width='100%' />
<Break />
<TextBox caption='Результат' id='TextBoxTabRes' captionWidth='1' editorWidth='3' width='100%' />
</Group>
|
Результат:

Теперь внесем изменения в функцию вычисления среднего:
| ButtonCalc_clicked() {
let sum = 0;
let cnt = 0;
this.controls.Grid1.dataSource().forEach(e => {
if (e.MaterialGroup() == this.controls.LookupMaterialGroup.value.Name) {
sum += e.Price();
cnt++;
}
});
this.controls.TextBoxTabRes.value = sum / cnt;
}
|
Результат:

Для того, чтобы код был окончательно пригоден к использованию, надо сделать проверку на содержимое лукапа, и при отсутствии значения в нем вычислять по всем строкам.
| ButtonCalc_clicked() {
let sum = 0;
let cnt = 0;
const mg = (this.controls.LookupMaterialGroup.value || {}).Name || '';
this.controls.Grid1.dataSource().forEach(e => {
if (mg == '' || e.MaterialGroup() == mg) {
sum += e.Price();
cnt++;
}
});
this.controls.TextBoxTabRes.value = sum / cnt;
}
|
Результат:

