Множественный выбор через Btk_ChoiceAbsAvi#
Btk_ChoiceAbsAvi добавляет к lookup-форме возможность отметить несколько записей и после подтверждения передать их ключи прикладному коду. Выбор сохраняется при обновлении и фильтрации списка, поэтому пользователь может сформировать итоговый набор в несколько действий.
Механизм только собирает выбор. Он не сохраняет выбранные записи в бизнес-сущность и не выполняет последующую бизнес-операцию: полученные ключи обрабатывает вызывающий код.
Типичные сценарии применения — выбор видов товарно-материальных ценностей, транспортных средств или финансовых документов. Далее идентификатор записи также называется ключом записи.
Как работает механизм#
Работа механизма состоит из следующих этапов:
Прикладной код открывает lookup со списком доступных записей.
Пользователь отмечает требуемые записи чекбоксами.
Механизм хранит сформированный набор, пока открыт текущий экземпляр формы.
Пользователь подтверждает выбор или отменяет форму.
После подтверждения прикладной код получает ключи отмеченных записей и выполняет требуемую бизнес-операцию.
Галочки и выделение строк#
Галочки и стандартное выделение строк в таблице выполняют разные задачи:
галочка показывает, входит ли запись в итоговый результат;
выделение одной или нескольких строк само по себе не добавляет их в результат;
групповая операция использует выделенные строки, чтобы сразу установить или снять у них галочки.
Пользователь может работать с выбором следующими способами:
Действие в форме |
Результат |
|---|---|
Установить или снять галочку |
Добавляет одну запись в итоговый набор или удаляет ее. |
Выделить строки |
Только подготавливает строки для групповой операции; итоговый набор не меняется. |
Выполнить «Выбрать выделенные записи» |
Устанавливает галочки у всех выделенных строк. |
Выполнить «Снять выбор с выделенных записей» |
Снимает галочки со всех выделенных строк. |
Выполнить «Очистить все» |
Снимает все установленные галочки. |
Операция выбора всех записей списка в общий механизм не входит. Если она нужна, ее реализуют в конкретном прикладном представлении.
Пример формы выбора с отмеченными записями:

Подключение к списку#
Механизм подключается к существующему списку Avi. Для работы выбора у каждой строки должен быть уникальный ключ, по которому механизм сохраняет и возвращает выбранные записи.
Определите ключ записи#
Выберите вариант CheckboxChoice, соответствующий типу ключа:
Вариант |
Тип ключа |
Стандартное имя ключа |
|---|---|---|
|
|
|
|
|
|
Если представление использует другое имя ключа, переопределите sKeyAttr в trait списка. Если имя отличается только в одном SQL-запросе, передайте его вторым аргументом choiceFlagSelect.
Подключите механизм к Avi#
Подмешайте Btk_ChoiceAbsAvi к классу прикладной выборки, а CheckboxChoiceNLong или CheckboxChoiceNGid — к trait списка в зависимости от типа ключа.
Ниже приведен минимальный шаблон. Замените ExampleAvi, ExampleDvi и List_ForChoose именами прикладных классов. Импорты базовых типов и методы, не относящиеся к механизму выбора, в шаблоне не показаны.
import ru.bitec.app.btk.sel.service.Btk_ChoiceAbsAvi
object ExampleAvi extends ExampleAvi
class ExampleAvi extends ExampleDvi with Btk_ChoiceAbsAvi {
def list_ForChoose(): List_ForChoose = {
new List_ForChoose {
override def meta: TypeTag = this
}
}
trait Default extends DviDefault
trait List extends Default with DviList
trait List_ForChoose extends List with CheckboxChoiceNLong {
// choiceFlagSelect добавляет признак выбранности для отображения чекбокса.
override protected def selectStatement: String = {
s"""
|select t.*,
| ${choiceFlagSelect("t")}
|from (${super.selectStatement}) t
|""".stripMargin
}
// Возвращает ключ и признак выбора в дополнительном запросе onRefreshExt.
override protected def onRefreshExt: String =
s"""WITH t AS (
| SELECT $sKeyParamAsAttr
|)
|SELECT t.$sKeyAttr,
| ${choiceFlagSelect("t")}
|FROM t
|""".stripMargin
}
}
Добавьте поля выбора в запросы#
В основной запрос списка добавьте результат choiceFlagSelect. В onRefreshExt также верните первичный ключ записи и результат choiceFlagSelect. Это позволяет механизму сформировать актуальное состояние чекбокса при обновлении данных представления.
В шаблоне выше эти требования выполняют два фрагмента:
${choiceFlagSelect("t")}добавляет служебные поля выбора в основной запрос иonRefreshExt;t.$sKeyAttrвозвращает первичный ключ строки для сопоставления данныхonRefreshExtс основным списком.
Если ключ выбора sKeyAttr отличается от первичного ключа строки, верните в onRefreshExt оба значения: первичный ключ с именем id, gid или gidRef и ключ выбора.
Настройте AVM#
Объявите bChoice_dz в блоке <attributes>, как показано в данном разделе, если нужно изменить наименование или порядок колонки. Без явного объявления механизм использует наименование " - " и порядок -100.
Для групповых операций включите мультиселект в отображении и таблице. Параметры doubleClickOperation.createFormMode и doubleClickOperation.lookupMode задают операцию, которую форма выполняет по двойному нажатию в соответствующем режиме. Операция changeSelectedByClick переключает состояние выбора текущей строки. Для обычного изменения чекбокса эти параметры не требуются.
<representation name="List_ForChoose"
editMode="edit"
isMultiSelect="true"
doubleClickOperation.createFormMode="changeSelectedByClick"
doubleClickOperation.lookupMode="changeSelectedByClick">
<layout>
<tabComposer>
<frame>
<grid isMultiSelectEnabled="true"/>
</frame>
</tabComposer>
</layout>
<attributes>
<attr name="bChoice_dz" caption="Выбор" order="-100"/>
</attributes>
</representation>
Откройте lookup и получите результат#
Откройте представление как lookup и передайте результат тому же представлению для разбора:
// Открывает список с чекбоксами и встроенными групповыми операциями.
val listRep = ExampleAvi.list_ForChoose()
val data = listRep.newForm().openLookup()
// Возвращает ключи записей, отмеченных пользователем.
val idavSelected = listRep.chosenKeys(data)
idavSelected.foreach { idvSelected =>
processSelected(idvSelected)
}
chosenKeys возвращает типизированный список ключей только для подтвержденного результата lookup. При отмене формы он возвращает пустой список. Если бизнес-логике нужно различать отмену и подтверждение без выбранных записей, дополнительно проверьте результат закрытия формы.
Дополнительные настройки#
Предварительный выбор#
Передайте параметр saPresetValues#, если часть записей должна быть отмечена при открытии формы. Ключи укажите одной строкой через разделитель ;.
val listRep = ExampleAvi.list_ForChoose()
val data = listRep
.newForm()
.params(Map("saPresetValues#" -> idavPreset.mkString(";")))
.openLookup()
val idavSelected = listRep.chosenKeys(data)
Ограничения#
Основной запрос и
onRefreshExtдолжны возвращать первичный ключ с именемid,gidилиgidRef, а также ключ выбораsKeyAttr, если он отличается от первичного.Порядок ключей в результате не гарантируется. Если порядок важен для бизнес-операции, вызывающий код формирует его самостоятельно.
Btk_ChoiceAbsAviне проверяет предметные ограничения и права на последующее изменение данных и не управляет транзакцией бизнес-операции. Эти задачи выполняет вызывающий код.