...

3.1. Виджет «Код»

Тема в разделе "Руководство по настройке форм и сценариев", создана пользователем ELMA365, 15 авг 2023.

  1. ELMA365

    ELMA365 Moderator

    Виджет Код позволяет работать напрямую с разметкой страницы. С его помощью можно как писать код для формы с нуля, используя HTML, CSS, JavaScript или TypeScript, так и встраивать готовые решения.

    Вы можете переопределить системные стили, добавить дополнительные обработчики на кнопки, задать собственное отображение таблиц и многое другое.

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

    Доработаем виджет для расчёта дат, который мы начали создавать для приложения Отпуск.

    Вынесем на поле для моделирования виджет Код. Откроется окно настроек. По умолчанию в него добавляется следующий код с примерами операндов:
    Код:
    
    <% if (false) { %>
    You can use the following instructions:
    Conditions: <% if (true /* Condition */) { %> ... <% } %>
    Iterators: <% for (const item of [] /* Array */) { %> ... <% } %>
    Values with HTML-escaping: <%- 'SomeValue' %>
    Values without HTML-escaping: <%= 'SomeValue' %>
    You can delete this block after reading.
    <% } %>
    Попробуем с помощью виджета Код задать для дат следующее отображение:
    Начало_периода - Конец_периода ( Х дней, Y раб.часов )

    Для этого удалим всё содержимое виджета и напишем следующий код:
    Код:
    
    <div class="days_count"> <!-- добавляем класс для использования в будущем -->
      <
    div>
        <%= 
    Context.data.first_date%> - <%= Context.data.second_date%>
        (<%= 
    Context.data.days_count%> дней, <%= Context.data.hours_count%> раб.часов)
      </
    div>
    </
    div>
    Запускаем отладку и вводим любые даты:

    [​IMG]

    Результат на форме сейчас выглядит следующим образом:

    [​IMG]

    Переменные first_date и second_date имеют тип Дата/время, и система не смогла привести их к строковому представлению.
    Переменные days_count и hours_count не отобразились, так как мы не рассчитали их значения.

    Обратите внимание, что сценарий не выдал ошибку, и остальной код отработал без проблем. Этот нюанс необходимо учитывать при разработке, чтобы не пропускать опечатки.

    Доработаем отображение дат, используя функцию format(), которая поддерживает формат moment:
    Код:
    
    <div class="days_count">
      <
    div>
        <%= 
    Context.data.first_date.format("DD.MM.YYYY") %> - <%= Context.data.second_date.format("DD.MM.YYYY")%>
        (<%= 
    Context.data.days_count%> дней, <%= Context.data.hours_count%> раб.часов)
      </
    div>
    </
    div>
    Добавим переменную для количества рабочих часов hours_count в контекст виджета. Затем на вкладке Сценарии дизайнера интерфейсов напишем сценарий для расчёта дней и часов:
    Код:
    
    async function onInit(): Promise<void> {
    const 
    firstDate Context.data.first_date!.asDatetime(new TTime());
    const 
    secondDate Context.data.second_date!.asDatetime(new TTime());

        const 
    duration =firstDate.sub(secondDate);
        
    Context.data.days_count Math.round(Math.abs(duration.days));
        
    Context.data.hours_count Math.abs(duration.hours);
    }
    При отладке получаем следующий результат:

    [​IMG]

    На данный момент количество рабочих часов вычислено неверно, так как не учитываются настройки рабочего календаря. Мы доработаем это в следующей главе.

    Настройки виджета на данном этапе выглядят так:

    Спойлер: Шаблон
    Виджет Код со следующим содержимым:
    Код:
    
    <div class="days_count">
      <
    div>
        <%= 
    Context.data.first_date.format("DD.MM.YYYY") %> - <%= Context.data.second_date.format("DD.MM.YYYY")%>
        (<%= 
    Context.data.days_count%> дней, <%= Context.data.hours_count%> раб.часов)
      </
    div>
    </
    div>

    Спойлер: Контекст
    [​IMG]

    Спойлер: Сценарий
    Код:
    
    /** Инициализация виджета */
    async function onInit(): Promise<void> {
        const 
    duration Context.data.first_date!.sub(Context.data.second_date!);
        
    Context.data.days_count Math.round(Math.abs(duration.days));
        
    Context.data.hours_count Math.abs(duration.hours);
    }

    Пользовательские виджеты внутри виджета «Код»

    В предыдущих главах мы рассмотрели, как создать и настроить собственный виджет. Сейчас рассмотрим, как с ним можно работать.

    После публикации виджет добавляется в общий список виджетов, и его можно использовать точно так же, как стандартные. Откроем любую форму или страницу в дизайнере интерфейсов и попробуем найти созданный виджет в общем списке на правой панели.

    [​IMG]

    Виджет можно добавить, к примеру, на форму приложения. При переносе виджета на поле для моделирования откроется окно настроек. Поля контекста, которые мы отметили как входные или выходные будут доступны для заполнения:

    [​IMG]

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

    Второй способ добавления пользовательского виджета на форму — это вызов специального метода в виджете Код с помощью контекстного меню:

    [​IMG]

    Система предложит выбрать виджет из списка. Обратите внимание, что ваш виджет может не отображаться в общем списке из-за настроек доступа. В этом случае перейдите в дизайнер интерфейсов и откройте вкладку Настройки. В зависимости от того, на каком уровне настроен ваш виджет, в блоке Доступные элементы разрешите доступ ко всем элементам или к элементам раздела. Подробнее читайте в статье «Дизайнер интерфейсов».

    После выбора виджета откроется окно его настроек. Свяжем виджет с контекстом приложения и контекстом формы:

    [​IMG]

    В итоге получим следующий код с разметкой:
    Код:
    
    <%= UI.widget.render('leave@days_count', {first_dateContext.data.date_startsecond_dateContext.data.date_enddays_countContext.data.dayshours_countViewContext.data.workminutes}) %>
    
    
    Отформатируем код и добавим признак, указывающий, что виджет используется только для чтения:
    Код:
    
    <%= UI.widget.render('leave@days_count',
        {
            
    readonlytrue,
            
    first_dateContext.data.date_start,
            
    second_dateContext.data.date_end,
            
    days_countContext.data.days,
            
    hours_countViewContext.data.workminutes
        
    }
    ) %>
    Для удобства не будем показывать содержимое виджета Код в разметке формы и зададим для него в нижней части окна настроек читаемое наименование, например, Количество дней [days_count].

    Виджет готов к использованию. В дизайнере форма с виджетом Код будет выглядеть следующим образом:

    [​IMG]

    Стандартные виджеты внутри виджета «Код»

    В виджете Код можно использовать не только пользовательские виджеты, но и стандартные виджеты системы, однако их набор ограничен. Доступны следующие варианты: Вкладки, Панель с заголовком, Выпадающее окно и Выпадающее меню. Подробнее об этом читайте в TS SDK в статье про API для отображения стандартных виджетов.

    Внутри виджета Код добавим на форму виджет Панель с заголовком и вложим в него созданный нами виджет Количество дней [days_count]:
    Код:
    
    <%= UI.widget.groupbox(
      {
        
    title'Количество рабочих дней',
        
    collapsibletrue// Сворачиваемая панель
      
    },
      
    panelDaysCount)
    %>
    <% 
    $template panelDaysCount %>
      <%= 
    UI.widget.render('leave@days_count',
          {
              
    readonlytrue// только для чтения
              
    first_dateContext.data.date_start,
              
    second_dateContext.data.date_end,
              
    days_countContext.data.days,
              
    hours_countViewContext.data.workminutes
          
    }
      ) %>
    <% 
    $endtemplate %>
    Посмотрим, как виджеты будут выглядеть на форме:

    [​IMG]

    Чтобы виджет с расчётом количества рабочих дней отрисовывался только тогда, когда обе даты введены, добавим условие:
    Код:
    
    <% if (Context.data.date_start && Context.data.date_end) { %>
      <%= 
    UI.widget.groupbox(
        {
          
    title'Количество рабочих дней',
          
    collapsibletrue// Сворачиваемая панель
        
    },
        
    panelDaysCount)
      %>
    <% } %>
    Функцию отрисовки содержимого панели panelDaysCount() можно оставить за скобками, так как здесь мы только определяем её, а вызов будет происходить при выполнении условия.
    Последнее редактирование: 16 авг 2023