﻿# Иерархическая структура

> [HTML Version](hierarchy-structure-widget.html)

Виджет позволяет отобразить данные двух связанных приложений в виде иерархической структуры. Пользователь увидит:

- иерархию элементов одного приложения в виде дерева, которое построено от заданного корневого элемента;

- списки элементов второго приложения, связанных с первым, а также данные этих элементов, которые переданы в виджет для их отображения.

Рассмотрим пример для двух приложений:

- **Места хранения **— содержит элементы, обозначающие склады, помещения, шкафы и полки. С помощью свойства **Родительское место хранения** в приложении задана подчинённость его элементов, которая отобразится в виджете: в складах есть помещения, в помещениях — шкафы, а в шкафах — полки;

- **Дела **— связано с `приложением` **Места хранения**. В карточке дела пользователь выбирает место его хранения. Так образуются списки дел, привязанные к определённым местам хранения. Эти списки с их данными, которые заданы для отображения, также можно показать в виджете.

**(hierarchy-structure-widget-1.PNG)**

В нашем примере виджет **Иерархическая структура** размещён на форме просмотра приложения **Места хранения**. Открыв карточку элемента **Архивное помещение**, пользователь увидит иерархию его дочерних мест хранения (шкафы и полки в этих шкафах), а также списки дел с разбивкой по шкафам и полкам, на которых эти дела хранятся. Кроме того, отобразится адрес email, заданный в карточке каждого дела.

Обратите внимание, для работы виджета используется клиентский скрипт. Он передаёт в виджет данные о корневом элементе первого приложения, а также списки элементов второго приложения, связанного с первым.

## Настроить работу виджета «Иерархическая структура»

Рассмотрим настройки, которые нужно выполнить для указанного выше примера. Они состоят из следующих этапов:

1. [Дополнить настройки формы приложения](#form-settings).

2. [Создать служебные переменные для работы виджета](#create-variables).

3. [Создать скрипт для работы виджета](#create-script).

4. [Добавить функцию инициализации](#initialization).

5. [Настроить виджет](#customize-widget).

### Шаг 1. Дополнить настройки формы приложения

1. Откройте **Настройки формы** приложения **Места хранения** и на вкладке [Контекст](360028941112.md) добавьте следующие свойства:

- **Родительское место хранения** — задаёт иерархию элементов, которая отобразится в виджете. В настройках свойства выберите тип **Приложение (один)** и укажите текущее приложение **Места хранения**;

**(hierarchy-structure-widget-2.PNG)**

- **Список дел** – определяет перечень элементов приложения **Дела**, связанных с текущим местом хранения, для их отображения в виджете. В настройках свойства выберите тип **Приложение (несколько)**, укажите приложение **Дела **и поле для связи **Место хранения**.

**(hierarchy-structure-widget-3.PNG)**

2. Вынесите свойство **Родительское место хранения **на формы создания, просмотра и редактирования приложения **Места хранения**. Это позволит пользователю указать родительский элемент в карточке места хранения и таким образом задать иерархию, которую покажет виджет **Иерархическая структура**.

### Шаг 2. Создать служебные переменные для работы виджета

На этом этапе создайте переменные, которые нужны для заполнения настроек виджета. Их значения определяются с помощью [скрипта](#create-script).

1. В дизайнере интерфейсов откройте форму просмотра приложения **Места хранения **и перейдите на вкладку **Контекст**.

2. Добавьте следующие переменные:

**(hierarchy-structure-widget-4.PNG)**

- **Корневое место хранения **(\[OBJECT\]) — передаёт в виджет значение элемента, от которого строится иерархия его дочерних элементов. Эта переменная с типом **Приложение (один)** в нашем примере ссылается на текущее приложение** Места хранения**;

- **Список дел общий** (\[OBJECT\]) — передаёт в виджет списки дел корневого и дочерних элементов, чтобы отобразить их. Эта переменная с типом **Приложение (несколько)** ссылается на приложение** Дела**; 

- **Поля для отображения в иерархической структуре** (\[OBJECT\]) — переменная произвольного типа, которая передаёт в виджет свойства приложения **Дела** для их отображения. В нашем примере в виджет передано свойство **Электронная почта**;

- **Показать пустую структуру **(\[OBJECT\])** **— переменная типа **Выбор «да/нет»**, которая определяет, нужно ли отобразить в виджете список дел для корневого элемента. Если в корневом месте хранения нет списка дел, то есть структура этого списка пустая, то свойству присваивается значение **true**.

### Шаг 3. Создать скрипт для работы виджета

Теперь в дизайнере интерфейсов перейдите на вкладку **Скрипты** и создайте клиентский [скрипт для работы виджета](https://elma365.com/ru/help/platform/client_server_scripts.html).

**(hierarchy-structure-widget-5.PNG)**

В скрипте задайте значения для переменных, созданных на предыдущем шаге, которые будут переданы в виджет через его [настройки](#customize-widget). Определите:

- корневой элемент иерархии, заполнив переменную \[OBJECT\]. В нашем примере в качестве корневого учитывается текущий элемент приложения** Места хранения**;

- общий список дел корневого и дочерних элементов иерархии, задав функцию, которая выполнится при инициализации форма просмотра. В нашем примере при выполнении функции \[OBJECT\] переменная \[OBJECT\] и заполнится значениями, заданными с помощью свойства [Список дел](#to-do-list) в каждом элементе иерархии (корневом и дочерних);

- поля связанного приложения **Дела**, которые нужно показать в виджете. Для этого заполните переменную \[OBJECT\]. В нашем примере для каждого дела задано отображение поля **Электронная почта**;

- наличие списка элементов приложения **Дело **для корневого места хранения. Для этого заполните переменную \[OBJECT\]. Это позволит корректно отобразить содержимое виджета.

Пример скрипта для работы виджета **Иерархическая структура**:

````
/\* Client scripts module \*/  
/\*\*Интерфейс для наименования столбцов в виджете Иерархическая структура\*/  
export interface ISelectedFieldItem \{  
    code: string;  
    name: string;  
\}  
async function onInit(): Promise<void> \{     
    let list\_selected\_field: ISelectedFieldItem\[\] = \[\{  
        code: '\_\_name',  
        name: 'Наименование Места хранения/Дела'  
    \},  \{  
        code: 'email',  
        name: 'Электронная почта'  
    \}\]  
    ViewContext.data.display\_properties = list\_selected\_field;  
    // Выбор текущего места хранения, от которого строится иерархическая структура  
    ViewContext.data.root\_storage = await ViewContext.fields.root\_storage.app.search().where(f => f.\_\_id.eq(Context.data.\_\_id)).first();    
    ViewContext.data.list\_case = \[\];  
    if(ViewContext.data.root\_storage) await fillListCase(ViewContext.data.root\_storage);  
  
    // Проверка есть ли дела в структуре хранения. Если нет, отображаем структуру без элементов  
    ViewContext.data.is\_show\_empty\_tree = \!ViewContext.data.list\_case || ViewContext.data.list\_case.length == 0;   
\}  
/\*\*Функция-рекурсия для поиска и заполнения Списка дел для виджета\*/  
async function fillListCase(root\_storage : BaseApplicationItemRef<Application\$debug\$storage\$Data, any>): Promise<void>\{  
    const list\_temp\_cases = await ViewContext.fields.list\_case.app.search().where((f,g) => g.and(f.\_\_deletedAt.eq(null), f.storage.link(root\_storage))).size(100).all();  
    if(\!ViewContext.data.list\_case) ViewContext.data.list\_case = \[\];  
    ViewContext.data.list\_case = ViewContext.data.list\_case.concat(list\_temp\_cases)  
    const list\_temp\_storage = await ViewContext.fields.root\_storage.app.search().where((f,g) => g.and(f.\_\_deletedAt.eq(null), f.parent\_storage.link(root\_storage))).size(100).all();  
    for(let storage of list\_temp\_storage)\{  
        await fillListCase(storage);  
    \}  
\} 

### ````
Шаг 4. Добавить функцию инициализации

Если скрипт задан, перейдите на вкладку **Настройки > Системные функции** и в поле **Инициализация** укажите функцию  \[OBJECT\] из скрипта, созданного на предыдущем шаге. Эта функция выполнится, когда пользователь откроет карточку места хранения. При этом сформируются списки дел для текущего и дочерних элементов иерархии, чтобы показать их в виджете. Обратите внимание, чем объёмнее структура иерархии, тем дольше будет открываться карточка элемента.

**(hierarchy-structure-widget-6.PNG)**

### Шаг 5. Настроить виджет

На этом этапе заполним настройки виджета заданными ранее [служебными переменными](#create-variables). Для этого перейдите на вкладку **Шаблон** и добавьте на форму просмотра виджет **Иерархическая структура**. В открывшемся окне настроек заполните поля:

**(hierarchy-structure-widget-7.PNG)**

- **Корневой элемент** — выберите служебную переменную **Корневое место хранения**, чтобы передать в виджет значение места хранения, карточка которого открыта для просмотра в текущий момент времени;

- **Поле для построения иерархии** — выберите свойство** Родительское место хранения** приложения **Места хранения**. Позволяет отобразить иерархию дочерних элементов в виджете;

- **Поле для связи** — выберите свойство **Место хранения** приложения **Дело**. Позволяет отобразить списки дел в виджете;

- **Список элементов связанного приложения\*** — выберите переменную, которая содержит список элементов приложения **Дела **для их отображения в виджете;

- **Поля связанного приложения для отображения\*** — выберите переменную **Поля для отображения в иерархической структуре**, чтобы передать свойства приложения **Дело **для их отображения в виджете;

- **Показать структуру без элементов связанного приложения\* **— включите эту опцию, если вы хотите показать в виджете только иерархию мест хранения без списков дел. Тогда списки связанных дел не отобразятся даже при их наличии.

**(hierarchy-structure-widget-8.PNG)**

Если списки дел нужно показать, справа от опции нажмите значок **(hierarchy-structure-widget-9.PNG)** и выберите переменную **Показать пустую структуру**. Она позволяет корректно отобразить содержимое виджета, если для корневого места хранения нет связанных с ним дел.

Сохраните и опубликуйте выполненные настройки.

Теперь, когда пользователь откроет карточку элемента приложения **Места хранения**, он увидит иерархию его дочерних элементов и списки элементов приложения **Дела**, связанные как с текущим элементом, так и с дочерними. В списках дел отобразятся также поля приложения **Дела**, которые заданы в настройках для работы виджета.