При автоматизации рабочего места кассира (РМК) часто возникает задача сделать интерфейс максимально отзывчивым и удобным. Одно из частых требований пользователей — мгновенный пересчет и показ сдачи прямо в процессе ввода полученной от покупателя суммы, без необходимости нажимать клавишу Enter или переключаться между полями.
Однако при попытке реализовать такую логику на управляемых формах разработчики часто сталкиваются с техническими сложностями: при обновлении данных на форме поле ввода сбрасывает набранный текст, выделяет его целиком либо вовсе теряет фокус клавиатуры. Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим правильные варианты реализации задачи.
Выясним причину, по которой стандартная форма управляемого приложения ведет себя подобным образом при динамическом обновлении:
Число). При программном изменении любых связанных данных на форме платформа пытается обновить визуальное состояние элемента управления, что приводит к перезаписи текущего буфера редактирования значением реквизита.&НаСервере), управляемая форма перерисовывается, что неизбежно приводит к потере фокуса каретки ввода.Проанализируем базовый и наиболее правильный подход на управляемых формах без вызовов сервера и сторонних компонент.
Разберем по шагам порядок настройки элемента:
ИзменениеТекстаРедактирования на клиенте.&НаКлиенте) и выводим результат в отдельный реквизит формы или элемент отображения (например, заголовок декорации или реквизит Сдача).Посмотрим на пример клиентского кода:
&НаКлиенте
Процедура ВнесеноИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
// Преобразуем введенный текст в число
ВнесеннаяСумма = Число(Текст);
// Рассчитываем сдачу на основе известной суммы чека
Сдача = ВнесеннаяСумма - СуммаЧека;
КонецПроцедуры
Если для вывода сдачи на форме используется элемент типа Декорация - Надпись, обновлять значение можно через свойство заголовка элемента:
&НаКлиенте
Процедура ВнесеноИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
ВнесеннаяСумма = Число(Текст);
ТекущаяСдача = ВнесеннаяСумма - СуммаЧека;
Если ТекущаяСдача >= 0 Тогда
Элементы.ДекорацияСдача.Заголовок = СтрШаблон("Сдача: %1 руб.", ТекущаяСдача);
Иначе
Элементы.ДекорацияСдача.Заголовок = "Недостаточно средств";
КонецЕсли;
КонецПроцедуры
Важно: Не выполняйте внутри этого обработчика запись в сам реквизит Внесено, пока пользователь не завершит ввод. Платформа запишет финальное значение в реквизит автоматически при потере фокуса или нажатии клавиши подтверждения.
Если расчет сдачи требует дополнительной валидации данных или работы со сложной логикой скидок/округлений, полезно добавить небольшую задержку, чтобы расчет не выполнялся при каждом микронажатии клавиши, а ждал завершения ввода пользователем.
Рассмотрим пример реализации через асинхронную задержку по таймеру:
&НаКлиенте
Перем пСуммаВвода, пТаймер;
&НаКлиенте
Процедура ВнесеноИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
пСуммаВвода = Число(Текст);
ВыполнитьПроверкуСдачи();
КонецПроцедуры
&НаКлиенте
Асинх Процедура ВыполнитьПроверкуСдачи()
Если пТаймер <> 0 Тогда
Возврат;
КонецЕсли;
пТаймер = ТекущаяУниверсальнаяДатаВМиллисекундах();
п = ТекущаяУниверсальнаяДатаВМиллисекундах();
Пока (п - пТаймер) < 300 Цикл
п = ТекущаяУниверсальнаяДатаВМиллисекундах();
КонецЦикла;
пТаймер = 0;
// Отображаем рассчитанный результат
Сдача = пСуммаВвода - СуммаЧека;
КонецПроцедуры
В типовых конфигурациях 1С (таких как 1С:Розница и 1С:Управление торговлей) для исключения ошибок ручного ввода часто используются другие эргономичные решения:
+100, +500, +1000, +5000, а также Без сдачи). Нажатие на кнопку сразу формирует сумму без использования клавиатуры и моментально рассчитывает сдачу.ПолеHTMLДокумента, передавая финальные данные в 1С через события клиентского скрипта.