Звездный рейтинг *****

06.04.20

Разработка - Работа с интерфейсом

Ранее я представил подсистему «Управление состоянием». К подсистеме был проявлен интерес, однако в рамках одной статьи аспекты её использования были представлены недостаточно полно. Более подробное рассмотрение использования подсистемы я планирую продолжить через публикацию отдельных учебные примеров. Это первая статья из цикла таких примеров.

Оглавление

 

Введение

Описание интерфейса

Создание формы

Взаимодействие

Описание модели

Модуль модели

Модель формы

Инициализация подсистемы

Проверка работы формы

Добавление связи

Расчет модели

Функция значения

Вывод

Источники


В этой статье я рассмотрю пример использования подсистемы "Управление состоянием". Пример имеет учебный характер. В дальнейшем я планирую публиковать и другие учебные примеры. Целью каждого такого примера будет рассмотрение отдельных аспектов используемой подсистемы. Начну я с самого простого: отображение состояния формы с использованием функций состояния.

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

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

В итоге мы построим обработку, где основная форма будет управляться через подсистему "Управление состоянием". На форме будет реализован нестандартный элемент управления, отображение которого будет управляться через подсистему. Сама модель будет реализована в общем модуле. В нем будут располагаться функции состояния и значения.

В примере используется нестандартный элемент формы, составленный из элементов декораций звезд двух видов: закрашенные и незакрашенные. Звезды располагаются в одну строку и вместе составляют шкалу звездного рейтинга от 0 до 5 закрашенных звезд. Состояние формы описывается одним параметром - Рейтинг. Рейтинг - это целое число от 0 до 5.

Необходимо реализовать такое поведение формы, при котором отображается шкала с числом закрашенных звезд равным величине выбранного рейтинга. При этом пользователь может выбрать одну из пяти звезд на шкале: если выбрана закрашенная звезда, то рейтинг понижается до уровня рейтинга выбранной звезды минус 1, если незакрашенная - рейтинг становится равным рейтингу звезды.

Для начала создадим обработку "Звездный рейтинг". У обработки будет один реквизит - Рейтинг (Число (1,0, положительное)).

Добавим основную форму обработки. В форме отключим автозаголовок и добавим 10 декораций типа Картинка: 5 закрашенных и 5 незакрашенных звезд. Имя декорации звезды сделаем таким, чтобы из него можно было бы получить информацию о рейтинге звезды и её состоянии закрашенная/незакрашенная. Для этого будем использовать следующий шаблон: ДекорацияЗвезда[Номер звезды][Состояние], где [Номер звезды] будет соответствовать величине рейтинга, а [Состояние] равно 1 - для закрашенной, а 0 - для незакрашенной звезды. На этом визуальная часть подготовки формы завершена.

Продолжим работу с формой в ее модуле. Для начала скопируем область кода "УправлениеСостоянием" из модуля формы документа ЗаявкаНаОперацию, который можно найти в демо конфигурации. Далее создадим обработчик события формы ПриСозданииНаСервере. В этом обработчике мы создадим описание модели формы.

Элементы формы вида полей ввода не нуждаются в дополнительном программировании, если необходимо реализовать изменение данных или расчет модели. Первое реализуется самой платформой стандартным поведением, второе - через подключение подсистемы "Управление состоянием". В нашем примере используется элемент формы вида декорация.

Поскольку элемент декорации звезды не является полем ввода, то стандартное взаимодействие с этим элементом не приведет к каким-либо изменениям данных. Исправим это, добавив в обработчик Нажатие код по изменению величины рейтинга в соответствии с нажатой звездой. Чтобы изменения отразились в модели используем функцию подсистемы РаботаСМодельюКлиентСервер.УстановитьЗначение для нового значения рейтинга. После внесения изменений нужно вызвать функцию УправлениеФормой, в которую необходимо передать массив измененных параметров состояния.

&НаКлиенте
Процедура ДекорацияЗвездаНажатие(Элемент)
  Перем ИзмененныеРеквизиты;
  //  Определение состояния звезды
  СоставИмениЭлементаЗвезды = СтрЗаменить(Элемент.Имя, "ДекорацияЗвезда", "");
  СостояниеЗвезды = Прав(СоставИмениЭлементаЗвезды, 1);
  РейтингЗвезды = Лев(СоставИмениЭлементаЗвезды, 1);
  //  Установка нового значения рейтинга по формуле: РейтингЗвезды - СостояниеЗвезды
  РаботаСМодельюКлиентСервер.УстановитьЗначение(ЭтотОбъект, "Рейтинг",, РейтингЗвезды - СостояниеЗвезды, ИзмененныеРеквизиты);
  //  Обновление формы
  УправлениеФормой(ИзмененныеРеквизиты);
  //  Возвращение фокуса на элемент звезды, которая была нажата
  ЭтотОбъект.ТекущийЭлемент = Элементы[СтрШаблон("ДекорацияЗвезда%1%2", РейтингЗвезды, ?(СостояниеЗвезды = "1", "0", "1"))];
КонецПроцедуры

Обратите внимание, что как такового расчета модели пока в нашем примере нет. Действительно, что рассчитывать, если параметр всего один? Однако обновление формы требуется. Может показаться, что передача единственного параметра в функцию УправлениеФормой не имеет смысла, однако есть смысл передавать в функцию список параметров, которые изменились фактически. Если изменения не произойдет, то и обновления формы не будет - в этом и заключается один из главных аспектов оптимизации работы с формой.

Использование модели состояний предполагает наличие общего модуля, функции которого могут быть доступны как в режиме сервера, так и клиента. Для нашего примера добавим такой общий модуль "МодельЗвездныйРейтинг". Установим признаки доступности модуля: Клиент, Сервер.

В модуль модели добавим функции состояния элементов формы. В нашем примере необходимо добавить функции состояния для всех звезд и одну для формы. Формат описания функции строго определен следующим образом: Функция Свойство[ИмяЭлемента](Свойства, Параметры) Экспорт ... КонецФункции. Для самой формы имя элемента используется следующее: "ЭтаФорма".

В функциях состояния необходимо задать свойства элемента по параметрам, переданным в функцию. Используем для определения видимости закрашенной звезды параметр Рейтинг по следующему условию: Рейтинг > (Рейтинг звезды - 1). Для незакрашенной звезды это условие будет таким: Рейтинг <  Рейтинг звезды.

Функция СвойстваЭтаФорма(Свойства, Параметры) Экспорт
  Свойства.Вставить("Заголовок", СтрШаблон("Выбран рейтинг %1", Параметры.Рейтинг));
  Возврат Истина;
КонецФункции
…
Функция СвойстваДекорацияЗвезда11(Свойства, Параметры) Экспорт
  Свойства.Вставить("Видимость", Параметры.Рейтинг > 0);
  Возврат Истина;
КонецФункции
…
Функция СвойстваДекорацияЗвезда10(Свойства, Параметры) Экспорт
  Свойства.Вставить("Видимость", Параметры.Рейтинг < 1);
  Возврат Истина;
КонецФункции
…

В этом примере в качестве объекта модели выступает форма. У формы единственный параметр состояния - Рейтинг. В системе нет необходимости описывать этот параметр отдельно. Также нет необходимости описывать какие-либо связи, т.к. других параметров просто нет.

Все что нам теперь остается - это добавить описание элементов формы в нашу модель. Формат описания предполагает перечисление элементов формы и параметров состояния, от которых они зависят.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
  //  Создание описания модели. Начало
  Модель = РаботаСМодельюКлиентСервер.Модель("МодельЗвездныйРейтинг", "Объект");
  //  Описание самой формы
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель,, "Рейтинг");
  //  Закрашенные звезды
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда11, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда21, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда31, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда41, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда51, "Рейтинг");
  //  Незакрашенные звезды
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда10, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда20, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда30, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда40, "Рейтинг");
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ДекорацияЗвезда50, "Рейтинг");
  //  Создание описания модели. Конец
  РаботаСМоделью.Инициализировать(ЭтотОбъект, Модель);
  //  Отображение состояния формы
  УправлениеФормойНаСервере();
КонецПроцедуры

Инициализация подсистемы в общем случае заключается в: создании структуры модели, определении топологического порядка параметров состояния, сохранении структуры модели в данных объекта, расчете производных (не сохраняемых) параметров состояния и только для формы - связывания элементов формы с моделью.

Вызов инициализации производится через единственную функцию подсистемы: Инициализация.

Для проверки работы полученной формы воспользуемся демо конфигурацией. Найти форму можно в меню Демо -> Сервис -> Звездный рейтинг. В конфигураторе это будет путь: Обработки->ЗвездныйРейтинг->ОсновнаяФорма.

Усложним наш пример. Введен еще один параметр состояния - Средний рейтинг. Пусть этот параметр условно рассчитывается по формуле: 0.5 * Рейтинг. Посчитанное значение будем отображать в заголовке формы.

…
  РаботаСМодельюКлиентСервер.Связь(ЭтотОбъект, Модель, "СреднийРейтинг", "Рейтинг");
  Модель.Параметры["СреднийРейтинг"].Выражение = "0.5 * Параметры.Рейтинг";
…

Для добавления параметра в нашу модель добавим новую связь Рейтинг -> Средний рейтинг. Отдельно описывать сам параметр обычно не требуется, и если в связи используется ранее неизвестный подсистеме параметр, то он автоматически добавляется в модель. Отдельно для нового параметра нам потребуется указать выражение его расчета.

На этом описание модели может быть завершено, однако, чтобы заголовок формы смог отображать его значение, нам необходимо в описание элемента ЭтаФорма добавить этот параметр.

…
  РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель,, "Рейтинг, СреднийРейтинг");
…

Затем в модуле модели для функции состояния ЭтаФорма нужно использовать новый параметр при формировании заголовка формы.

Функция СвойстваЭтаФорма(Свойства, Параметры) Экспорт
  Свойства.Вставить("Заголовок", СтрШаблон("Выбран рейтинг %1, средний - %2", Параметры.Рейтинг, Параметры.СреднийРейтинг));
  Возврат Истина;
КонецФункции

Запустим нашу обработку, откроем её форму и убедимся в её НЕработоспособности.

В главе "Взаимодействие" говорилось, что предыдущий пример не требует расчета модели, поэтому в нашем нестандартном элементе управления достаточно после изменения параметра Рейтинг просто вызвать функцию обновления формы УправлениеФормой (или, как принято у вебщиков - рендеринга). Однако во втором примере ситуация резко поменялась - у нас появилась связь, а значит есть зависимость, которую нужно рассчитать после изменения.

Для исправления ситуации достаточно заменить вызов функции обновления формы УправлениеФормой на функцию расчета состояния: РассчитатьСостояние, определенной также в контексте модуля формы.

Однако не всегда расчет параметра состояния возможно описать простым выражением. Усложним наш пример. Пусть средний рейтинг будет рассчитываться из данных рейтинга банков, значения которых хранятся в регистре сведений РейтингБанков.

Если выражение расчета не удается представить в простом виде, то можно использовать функцию значения. Добавим в нашу модель в общем модуле новую функцию значения для параметра "Средний рейтинг". Формат такой функции следующий: Функция Значение[Имя параметра](Контекст, Объект, Модель, Параметры, СтандартнаяОбработка) Экспорт. В самом параметре для выражения установим значение "*", что означает использование функции значения.

#Если Сервер Тогда
Функция ЗначениеСреднийРейтинг(Контекст, Объект, Модель, Параметры, СтандартнаяОбработка, Отказ) Экспорт
  Запрос = Новый Запрос;
  Запрос.Текст =
  "ВЫБРАТЬ
  |  СУММА(РейтингБанков.Рейтинг) КАК СуммаРейтинга,
  |  КОЛИЧЕСТВО(РейтингБанков.Рейтинг) КАК КоличествоРейтинга
  |ИЗ
  |  РегистрСведений.РейтингБанков КАК РейтингБанков";
  Выборка = Запрос.Выполнить().Выбрать();
  Если Выборка.Следующий() И Выборка.КоличествоРейтинга > 0 Тогда
    Возврат Окр((Выборка.СуммаРейтинга + Параметры.Рейтинг) / (Выборка.КоличествоРейтинга + 1), 2);
  Иначе
    Возврат Параметры.Рейтинг;
  КонецЕсли;
КонецФункции
#КонецЕсли

Здесь проявляется еще один аспект работы подсистемы - требование контекста вычисления параметра состояния. Укажем этот контекст через признак параметра НаСервере = Истина.

...
  РаботаСМодельюКлиентСервер.Связь(ЭтотОбъект, Модель, "СреднийРейтинг", "Рейтинг");
  Модель.Параметры["СреднийРейтинг"].Выражение = "*";
  Модель.Параметры["СреднийРейтинг"].НаСервере = Истина;
...

Вывод

На достаточно простом примере был показан процесс создания модели работы формы и инициализации подсистемы Управление состоянием. Если процесс подключения подсистемы разложить на последовательность шагов, то это может выглядеть так:
  1. В модуль формы перенести область кода Управление состоянием из демо конфигурации
  2. Создать обработчик ПриСозданииНаСервере, в котором сделать описание модели формы. Добавить в обработчик:
    1. вызов инициализации подсистемы
    2. вызов обновления формы
  3. Добавить общий модуль модели, в котором разместить функции состояния и функции значения.

Вот так, на Раз, Два, Три мы подключили подсистему Управление состоянием к нашей форме.

Пример навеян следующими публикациями:

Интерфейс Работа с формой

См. также

Богатый редактор картинок, хранимых в базе, с возможностью РИСОВАНИЯ. Редактор внешних файлов картинок. Объект, расширяющий возможности работы с картинками из встроенного языка (Три в одном) + Обработка «Стандартизация картинок»

Работа с интерфейсом Рабочее место Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Обработка предназначена для редактирования картинок в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Также обработка может быть использована из встроенного языка как объект для редактирования картинок. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Данная обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    61810    43    59    

80

[Расширения] Динамическое управление видимостью и доступностью элементов форм (УФ) (8.3.6+)

Работа с интерфейсом Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    54410    16    21    

42

Управление дашбордами

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Обработка предназначена для создания и управления дашбордами.

2400 руб.

29.06.2020    16702    21    4    

35

Новогоднее оформление для 1С

Работа с интерфейсом Платформа 1С v8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Добавьте новогоднего настроения! Расширение создает декорацию в виде гирлянды на некоторых формах объектов.

27.12.2023    10750    750    elcoan    45    

106

Конструктор HTML, CSS и javascript

Инструментарий разработчика Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Подходит для создания web-страниц для замены управляемых форм 1С, красивых отчетов, интерфейса мобильного приложения на платформе 1С и для простых страниц веб-сайтов.

2 стартмани

10.04.2023    9628    151    acces969    31    

118

Модель состояния для MVC

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    3671    kalyaka    2    

27

Табло очереди заказов на экран телевизора

WEB-интеграция Работа с интерфейсом Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для 1С: Розница 2.3.

3600 руб.

29.04.2022    12086    1    5    

10
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. pm74 199 08.04.20 15:33 Сейчас в теме
хм, и ни одного отзыва . это очень демотивирует . Имо все выглядит слишком сложно ( на первый взгляд).
2. CyberCerber 853 09.04.20 11:54 Сейчас в теме
Прочитал полностью статью. Было сложно, но прочитал.
Если на этом простом примере вы хотели показать плюсы вашей системы, то у вас, к сожалению, не получилось... Очень, очень, сложно и не понятно даже в таком простом примере. Я не знаю, как сторонний разработчик сможет заставить себя такое сделать. Иногда, когда платформа не предоставляет каких-то средств и технологий с этим приходится просто смириться, а не достраивать сверху свое, ничего работоспособного может не получиться.

Конкретные замечания/вопросы по примеру:
1. Всю красоту сразу убивает дублирование кучи элементов. Когда есть такой однородный набор, то элементы создают программно динамически. У вас такое возможно? В модуле модели я увидел по методу на каждый элемент. Выходит, динамически создать и привязать не получится? И еще вы написали про 8 элементов, почему не 10?
2. Переменные РейтингЗвезды, СостояниеЗвезды - числового или строкового типа?
3. В чем смысл среднего рейтинга? Почему он просто делится на два от обычного, а на скрине они равны?
3. kalyaka 1053 09.04.20 23:51 Сейчас в теме
(2)
показать плюсы вашей системы
Нет, цель этого примера в том, чтобы показать как начать работать с подсистемой. В примере последовательно вводятся основные понятия подсистемы: Функция состояния, Параметр состояния, Связи. Плюсы нужно искать в основной статье.
как сторонний разработчик сможет заставить себя такое сделать
Тут все очень просто: если усилия на изучение новой технологии меньше получаемых преимуществ от её использования, то есть смысл ее изучать. Я исхожу из того, что преимущества использования превышают затраты.
когда платформа не предоставляет каких-то средств и технологий с этим приходится просто смириться
Но тогда придется смириться и с тем, что у кого то будет получаться делать на платформе такие вещи, которые она сама делать не умеет и этот кто-то будет вашим конкурентом :)
1.
дублирование кучи элементов
Не понял, что вы имели в виду? Если то, что каждый элемент интерфейса описывается отдельно?
В модуле модели я увидел по методу на каждый элемент
Это заложено в архитектуре решения. Я об этом писал в основной статье в разделе Группировка данных и элементов В принципе, для приведенного здесь примера можно и одну функцию написать. Это будет тогда такой компонентный подход. Однако суть примера не в оптимизации, а в наглядном представлении использования основных понятий подсистемы.
Выходит, динамически создать и привязать не получится?
Я предполагаю в дальнейшем сделать конструктор кода, с помощью которого можно будет генерировать код модуля и просто вставлять в конфигурацию по аналогии как это сделано с правилами обмена в конвертации
вы написали про 8 элементов, почему не 10
Это просто опечатка :), исправил
2. РейтингЗвезды - это параметр состояния, значение которого сохраняется в реквизите формы. СостояниеЗвезды - это характеристика конкретной декорации, которую я использую для вычисления рейтинга звезды. Поскольку СостоянияЗвезды я нигде не храню, а вычленяю из имени декорации, то ее тип строковый.
3.
В чем смысл среднего рейтинга?
У этого параметра два смысла. 1-й - это показать как ввести в систему расчетный параметр, значение которого может определяться через выражение или через функцию значения. 2-й смысл для примера это средний рейтинг банков, который вычисляется как среднее значение рейтингов из данных регистра сведений
Почему он просто делится на два от обычного, а на скрине они равны
Для примера мне нужно было показать как значение параметра может задаваться выражением. Вот я и взял выражение перемножения некоторого числа, скажем 0.5 на значение параметра состояния Рейтинг. Далее в примере я уже выражение заменил на функцию значения и здесь мне уже потребовался контекст сервера.

А скрин - это просто иллюстрация формы с моделируемым интерфейсным элементом *****
4. anri99 01.06.23 16:58 Сейчас в теме
Вот вариант проще:

&НаКлиенте
Процедура УстановитьОценку(Элемент)
	Объект.Оценка = Число(Прав(Элемент.Имя,1));  
	ОтрисоватьЗвезды();
КонецПроцедуры

&НаКлиенте
Процедура ОтрисоватьЗвезды()  
	Для Сч = 1 По 5 Цикл
		Если Сч <=Объект.Оценка Тогда
			Элементы[СтрШаблон("Звезда%1",Сч)].Картинка = БиблиотекаКартинок.ЗвездаАктивная;
		Иначе
			Элементы[СтрШаблон("Звезда%1",Сч)].Картинка = БиблиотекаКартинок.ЗвездаНеактивная;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
Показать
5. kalyaka 1053 01.06.23 20:51 Сейчас в теме
(4) Ваше решение тоже рабочее:)
Вы использовали процедурную парадигму кода, а в статье приводится решение в функциональной парадигме в контексте использования шаблона MVC.
Оставьте свое сообщение