META

Смарт-формы

Мотивация

Довольно часто нужно нарисовать типовую форму для добавления или редактирования строки таблицы Логированиче через ObjectLogService будет выполнено автоматически, а значит и Шина сможет принять событие, если будет нужно.

Автоматическая генерация формы

Форма генерируется по внутреннним правилам, но подвигать контролы можно через их позициии в списке fields в yaml файле или атрибут order, но даже это не гарантирует, что они выстроятся в нужном вам порядке - мета сортирует блоками в соответствии со внутренними правилами.

Тип me-input так же пытается подобраться автоматически, исходя из заполненности полей:

  • name
  • db_type
  • data_type
  • semantic_role

Ширина me-input для поля высчитывается автоматически исходя из разных параметров, но может быть задана через атрибут поля lego_elem.span. В целом иногда есть задача вывести поле как textarea, для этого используется атрибут lego_elem. По сути там пишется все то, что можно писать в обычных ручных lego формах, но не обязательно описывать вообще все - впишите только то, что нужно переопределить по отношению к автосгенерированным свойствам.

Например:

...
- alias: name
  db_type: text
  is_title: true
  display_name: Название клиента
  name: name
  semantic_role: DIMENSION
  order: 100 <---------- сортировка, заданная вручную и не через само положение относительно других полей entity
  data_type: TEXT
  is_required: true
  lego_elem:  <---- Все то, что рабоатет в lego формах (НЕ ОЯЗАТЕЛЬНО полное описание всего elem). Перетирается важными сгенерированными параметрами, например id, label, entityId, required и пр 
    name: me-input
    span: 4
    attrs:
      type: textarea
...

Настройка insert_query

Иногда бывает, что надо вызвать хранимую процедуру для вставки объекта. Это можно сделать через настройку параметра insert_query в yaml, нужной entity. Данные формы придут как обычно в :env.sp.obj.*

ВАЖНО! Вы будете обязаны вернуть одну строку с одним полем с названием id.

Параметры add_expression и set_expression

Иногда при insert или update записи надо иметь высчитываемые поля, но часто они зависят от контекста, например userId. В примере нише рассматривается простейший случай, когда нам надо просто взять и вставить id пользователя (используется prepared statement), но тут можно написать и более сложный sql expression

- name: author_user_id
  db_type: bigint
  display_name: Добавлено
  i18n: true
  foreign_entity_id: 2654
  is_readonly: true
  add_expression: :env.userId
- name: last_user_id
  db_type: bigint
  display_name: Изменено
  i18n: true
  foreign_entity_id: 2654
  is_readonly: true
  add_expression: :env.userId
  set_expression: :env.userId

Практический пример

Пример настройки entity

id: '190'
name: Клиент
db_alias: adplatform
schema: public
table: client
alias: client
kind: DICT
metaql_where: '#table.id in (select client_id from get_user_clients(${env.userId?number}))'
input_options_query: >
  select
    client.id,
    client.name,
    categories.name as description
  from client
    left join company on company_id = company.id
    left join client_category as categories on categories.id = client.category_id
  where client.is_enabled
  AND client.company_id=:env.companyId::bigint
  AND client.id in (select client_id from get_user_clients(:env.userId::bigint) )
  ORDER BY 2

insert_query: >
  SELECT client_id as id FROM ext_garpun_main."api_addClient"(
    :env.userId::bigint, :env.companyId::bigint,
    :env.sp.obj.name::text, 11
  );
search_order: 1
object_list_base_page_id: '2176'
acl: 
  view:   /* Не забывайте про ACL. У вас он может быть другой  */
    roles:
    - meta.role.auth
fields:
- alias: id
  db_type: bigint
  is_primary: true
  name: id
  display_name: ID
  semantic_role: DIMENSION
  data_type: LONG
  is_disabled: true
- alias: name
  db_type: text
  is_title: true
  display_name: Название клиента
  name: name
  semantic_role: DIMENSION
  data_type: TEXT
  is_required: true
- alias: is_enabled
  db_type: bool
  name: is_enabled
  display_name: Активный
  semantic_role: DIMENSION
  data_type: BOOLEAN
- alias: is_archived
  db_type: bool
  name: archive
  display_name: Архивный
  semantic_role: DIMENSION
  data_type: BOOLEAN
- alias: category_id
  db_type: int8
  name: category_id
  data_type: LONG
  foreign_entity_id: 2768
  semantic_role: DIMENSION
  default_value: 11
- alias: creation_time
  db_type: timestamp(0)
  name: creation_time
  display_name: Дата создания
  i18n: true
  data_type: DATETIME
  semantic_role: DIMENSION
  is_disabled: true
- alias: modification_time
  db_type: timestamp(0)
  name: modification_time
  display_name: Дата изменения
  i18n: true
  data_type: DATETIME
  semantic_role: DIMENSION
  is_disabled: true

Пример 1

Например мы хотим получить форму редактирования всех полей нужной entity_id. Добавляем страницу в рамках нужной entity. В нашем случае для примера 190. Url меты должен быть примерно таким, когда вы работаете со страницей - /card?e=190&o={ТУТ_ID_ОБЪЕКТА} Это все, что надо на странице:

<script type="meta/js" elem="me-smart-form" id="smart_form">
function main(SmartFormService, pvm, vm, env, originalEnv) {
  SmartFormService.handle(env, originalEnv, vm, pvm);
}
</script>

Мета автоматически нарисует текствые поля для ввода текстовых значений, чекбоксы для boolean, нарисует выпадашки для полей, с указанным foreign_entity_id

Пример 2

Мы хотели получить редактор записи клиента, но так, чтобы при добавлении было только поле name, а при редактировании к нему добавлялся бы выбор category_id

Это все, что надо на странице:

<script type="meta/js" elem="me-smart-form" id="smart_form">
function main(SmartFormService, pvm, vm, env, originalEnv) {
  var fieldNames = ['name'];
  if (env.hasObjectId) {
    fieldNames.push('category_id');
  }
  SmartFormService.handle(env, originalEnv, vm, pvm, {
    fieldNames: fieldNames
  });
}
</script>

Что далее?

Не забудьте про обработчик событий сущности check_access для того, чтобы не делать проверку доступа к объекту на каждой странице сущности.