Частично загружаемые деревья#

Частично загружаемое дерево — это вид отображения, в котором список в форме дерева загружается из базы данных только для корневых записей и дочерних записей раскрытых узлов.

Частично загружаемые деревья используются для отображений, в которых заведомо ожидается большое количество записей и полная загрузка данных при открытии выборки не требуется. Например, частичная загрузка используется для дерева Mct_Structure.

Для работы частично загружаемого дерева необходимо:

  1. Отключить полную загрузку дерева в AVM-разметке.

  2. Указать атрибуты идентификатора, родительской записи и наличия дочерних записей.

  3. Обработать системные параметры раскрытых узлов в операции refresh.

  4. Ограничить результат запроса корневыми записями и содержимым раскрытых узлов.

Настройка отображения#

Для отключения полной загрузки дерева в настройках отображения 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, даже если при установке параметров возникнет ошибка.