Частично загружаемые деревья#
Частично загружаемое дерево — это вид отображения, в котором список в форме дерева загружается из базы данных только для корневых записей и дочерних записей раскрытых узлов.
Частично загружаемые деревья используются для отображений, в которых заведомо ожидается большое количество записей и полная загрузка данных при открытии выборки не требуется. Например, частичная загрузка используется для дерева Mct_Structure.
Для работы частично загружаемого дерева необходимо:
Отключить полную загрузку дерева в AVM-разметке.
Указать атрибуты идентификатора, родительской записи и наличия дочерних записей.
Обработать системные параметры раскрытых узлов в операции
refresh.Ограничить результат запроса корневыми записями и содержимым раскрытых узлов.
Настройка отображения#
Для отключения полной загрузки дерева в настройках отображения AVM-файла укажите свойство:
fetchAllTree="false"
В настройках фрейма укажите:
атрибут идентификатора записи;
атрибут идентификатора родительской записи;
атрибут, содержащий признак наличия дочерних записей.
Пример:
<tree idAttr="gid"
idParentAttr="gidParent"
hasChildrenAttr="bHasChild"/>
В примере:
gid— идентификатор записи;gidParent— идентификатор родительской записи;bHasChild— признак наличия дочерних записей.
Значение атрибута, указанного в hasChildrenAttr, определяет, может ли пользователь раскрыть соответствующий узел.
Системные параметры дерева#
Для определения раскрытых узлов используются параметры выборки:
OPENNODEIDARRAY— список идентификаторов раскрытых узлов, разделённых запятыми, в форматеftString;OPENNODEID— значениеidAttrраскрываемого узла в форматеftString.
Параметр OPENNODEIDARRAY используется при обновлении дерева. Параметр OPENNODEID передаётся при раскрытии отдельного узла.
OPENNODEIDARRAY и OPENNODEID являются системными параметрами. Устанавливать их значения вручную нельзя.
Формирование запроса#
Запрос операции refresh должен возвращать:
корневые записи дерева;
записи, относящиеся к раскрытым узлам;
дочерние записи узла, который раскрывается пользователем;
признак наличия дочерних записей.
Для загрузки данных используются значения idAttr и idParentAttr, переданные через системные параметры дерева.
Ниже приведён пример запроса для Mct_StructureAvi#StructureTree, расположенного в пакете Mct_StructurePkg.getOnRefreshBs.
-- п. 1. Открытые узлы
with nodes as (
select distinct tVal.tVal as gid
from regexp_split_to_table(
concat_ws(
', ',
:OpenNodeIdArray#,
:OpenNodeIdArray
),
', '
) tVal
where :OpenNodeId is null
union
select :gidParent as gid
where :gidCurrentGid# is not null
),
-- Фильтрация объектов для вывода в дерево
gidFlt as (
select h.gid,
h.gidParent
from (
-- п. 2. Обновление раскрытых узлов RefreshNodes
select t.gid,
case
when ll.id is null then null
else l.gidParent
end as gidParent
from mct_structure t
join mct_structurelink l
on l.gidstructure = t.gid
left join mct_structurelink ll
on l.gidparent = ll.gidstructure
and l.idviewtype = ll.idviewtype
where t.idPrjVer = :flt_idPrjVer
and l.idviewtype = :flt_idViewType
and l.gidparent in (
select n.gid
from nodes n
)
union all
-- п. 3. Корневые записи
select t.gid,
null as gidParent
from mct_structure t
join mct_structurelink l
on l.gidstructure = t.gid
where t.idPrjVer = :flt_idPrjVer
and l.idviewtype = :flt_idViewType
and not exists (
select 1
from mct_structurelink ll
where ll.gidstructure = l.gidparent
and ll.idviewtype = :flt_idViewType
)
and :OpenNodeId is null
union all
-- п. 4. Дочерние записи раскрываемого узла
select l.gidstructure as gid,
l.gidparent
from mct_structurelink l
where l.idviewtype = :flt_idViewType
and l.gidparent = :OpenNodeId
) h
)
-- п. 5. Основной запрос
select t.id,
t.idClass,
t.gid,
tt.gidParent,
(
select coalesce(max(1), 0)
from mct_structurelink l
where l.gidparent = t.gid
) as bHasChild,
t.gidDoc,
t.gidDocVer,
t.gidSourceObj,
t.idPrjVer,
t1.sCode as idPrjVerHL,
t.idEskd,
t2.sCaption as idEskdHL,
t.idPosType,
t3.sCaption as idPosTypeHL,
t.sCode,
t.sCaption,
t.sSysName
from Mct_Structure t
join gidFlt tt
on t.gid = tt.gid
left join Bs_PrjVer t1
on t.idPrjVer = t1.id
left join Mct_Eskd t2
on t.idEskd = t2.id
left join Mct_PosType t3
on t.idPosType = t3.id
left join Bs_Goods t4
on t.idGds = t4.id
left join Msr_MeasureItem t5
on t.idMsr = t5.id
left join Mct_OrderSheet t6
on t.idOrderSheet = t6.id
Блоки запроса выполняют следующие задачи:
п. 1 — формирует таблицу значений раскрытых узлов с учётом узла, созданного на следующем уровне;
п. 2 — получает записи, относящиеся к раскрытым узлам;
п. 3 — получает корневые записи дерева;
п. 4 — получает записи узла при его первом раскрытии;
п. 5 — возвращает атрибуты, необходимые для формирования строк дерева.
Признак наличия дочерних записей#
Основной запрос должен возвращать атрибут, указанный в свойстве hasChildrenAttr.
В примере используется атрибут bHasChild:
(
select coalesce(max(1), 0)
from mct_structurelink l
where l.gidparent = t.gid
) as bHasChild
Значение атрибута показывает, существуют ли у записи дочерние элементы.
Без этого признака дерево не может определить, требуется ли отображать для записи элемент раскрытия узла.
Ограничение списка записей#
Результат основного запроса ограничивается содержимым gidFlt:
join gidFlt tt
on t.gid = tt.gid
В gidFlt входят:
корневые записи;
записи раскрытых узлов;
дочерние записи узла, который пользователь раскрывает в текущий момент.
За счёт этого выборка не загружает полное дерево при каждом выполнении refresh.
Загрузка дочерних записей при открытии#
Чтобы открыть выборку с предварительно загруженными дочерними записями, при открытии можно передать список узлов и использовать его в операции refresh.
При таком способе дочерние записи загружаются из базы данных, но соответствующие узлы остаются свёрнутыми. Пользователю потребуется раскрыть их вручную.
Примечание
Изменение параметров, используемых в запросе, вызывает операцию refresh.
Изменение параметров без refresh#
Чтобы установить параметры без вызова refresh, на время их изменения установите selection.ignoreParamChange в значение true.
После установки параметров необходимо вернуть selection.ignoreParamChange в значение false.
Пример:
try {
selection.ignoreParamChange = true
setVar("gidParent", curGidParent)
setVar("gidCurrentGid#", thisRop().gid)
} finally {
selection.ignoreParamChange = false
}
Конструкция try и finally обеспечивает восстановление значения selection.ignoreParamChange, даже если при установке параметров возникнет ошибка.