При работе с платформой 1С:Предприятие 8.3 и управляемыми формами, разработчики часто сталкиваются с необходимостью организовать взаимодействие между полем HTML-документа и клиентским кодом формы. Однако, методы, которые работали в более ранних версиях платформы (например, до 8.3.14), могут перестать функционировать, вызывая затруднения. В этой статье мы подробно рассмотрим, почему старые подходы больше не работают и как реализовать двустороннюю связь между JavaScript внутри HTML-поля и вашей управляемой формой 1С в современных версиях платформы.
Ранее существовала распространенная практика передачи объекта управляемой формы напрямую в глобальную переменную JavaScript внутри HTML-документа. Эта техника заключалась в использовании кода 1С, подобного приведенному в исходном сообщении:
&НаКлиенте
Процедура ПолеHTMLДокументаДокументСформирован(Элемент)
Элементы.ПолеHTMLДокумента.Документ.DefaultView.externalForm = ЭтотОбъект;
КонецПроцедуры
Предполагалось, что после выполнения этого кода, в JavaScript-коде HTML-додокумента переменная externalForm будет содержать ссылку на текущую управляемую форму 1С, позволяя вызывать её экспортные клиентские методы. Однако, как верно подмечено в исходной теме, такая конструкция теперь приводит к тому, что externalForm становится неопределено (undefined) в JavaScript, хотя передача примитивных типов данных (строк, чисел) по-прежнему работает.
Выясним причину этой неработоспособности. Существует несколько ключевых изменений в платформе 1С, которые привели к такому поведению:
Документ у ПолеHTMLДокумента изменило свой тип. Ранее оно могло быть COMОбъект, что позволяло более глубокую интеграцию. Теперь оно часто возвращает ВнешнийОбъект, который имеет более ограниченный набор методов и свойств для взаимодействия, направленный на управляемый обмен данными, а не на прямую передачу объектов.
Таким образом, старый подход, основанный на прямой передаче объекта формы, стал неактуальным и небезопасным. Нам потребуется использовать новые, более структурированные и контролируемые механизмы для организации взаимодействия.
Несмотря на усиление изоляции, возможности двустороннего взаимодействия между полем HTML-документа и управляемой формой 1С остались, но они реализуются по-другому. Мы рассмотрим два основных метода:
Эти подходы позволяют безопасно и контролируемо обмениваться данными и вызывать нужные функции с обеих сторон (например, когда внедряются Яндекс-карты в 1С).
Этот метод является одним из наиболее распространенных и надежных для инициирования вызова методов 1С из JavaScript. Он основан на имитации пользовательского действия и использовании события ПриНажатии поля HTML-документа.
Внутри вашего HTML-файла, который отображается в поле ПолеHTMLДокумента, мы размещаем один или несколько скрытых элементов. Эти элементы не будут видны пользователю, но будут служить "каналом связи" для передачи информации и запуска событий.
Например, мы можем использовать скрытый div или input type="hidden":
<!-- В вашем HTML-документе -->
<div id="externalFormCaller" style="display: none;"></div>
Этот элемент div с идентификатором externalFormCaller будет нашим посредником. Важно, чтобы он был скрыт с помощью display: none; или visibility: hidden;.
Когда нам нужно вызвать метод 1С из JavaScript, мы будем помещать имя этого метода и необходимые параметры в атрибуты или текстовое содержимое нашего скрытого элемента. Затем мы программно "нажмем" на этот элемент.
Пример JavaScript-кода:
// В вашем JavaScript-коде внутри HTML-документа
function call1CMethod(methodName, params) {
var caller = document.getElementById('externalFormCaller');
if (caller) {
// Преобразуем параметры в строку JSON для удобства передачи
var data = {
method: methodName,
parameters: params
};
caller.setAttribute('data-payload', JSON.stringify(data));
// Имитируем нажатие на скрытый элемент
var event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
caller.dispatchEvent(event);
}
}
// Пример использования:
// call1CMethod('МойКлиентскийМетод1С', { Имя: 'Иван', Возраст: 30 });
Здесь функция call1CMethod принимает имя метода 1С и объект с параметрами. Она записывает их в атрибут data-payload скрытого элемента externalFormCaller в формате JSON, а затем программно вызывает событие click на этом элементе.
В управляемой форме 1С, для поля HTML-документа мы должны обработать событие ПриНажатии. Этот обработчик срабатывает, когда пользователь (или JavaScript программно) "нажимает" на какой-либо элемент внутри HTML-документа. Важным моментом является то, что в обработчик передается информация об элементе, по которому произошло нажатие.
Пример кода 1С:
&НаКлиенте
Процедура ПолеHTMLДокументаПриНажатии(Элемент, ДанныеНажатия)
Если ДанныеНажатия.ИдентификаторЭлемента = "externalFormCaller" Тогда
// Мы определили, что нажатие произошло на нашем скрытом элементе
ПереданныеДанныеJSON = ДанныеНажатия.HTMLЭлемент.getAttribute("data-payload");
Если Не ЗначениеЗаполнено(ПереданныеДанныеJSON) Тогда
Возврат;
КонецЕсли;
// Десериализуем JSON-строку в Структуру или Соответствие 1С
Попытка
ПереданныеДанные = JSON.Прочитать(ПереданныеДанныеJSON);
Исключение
// Обработка ошибки парсинга JSON
Сообщить("Ошибка парсинга JSON: " + ОписаниеОшибки(), СтатусСообщения.Важное);
Возврат;
КонецПопытки;
ИмяМетода = ПереданныеДанные.method;
Параметры = ПереданныеДанные.parameters;
// Вызываем соответствующий клиентский экспортный метод формы
// Убедитесь, что метод 'МойКлиентскийМетод1С' существует
// и имеет атрибут &НаКлиенте, а также принимает Параметры
Если ИмяМетода = "МойКлиентскийМетод1С" Тогда
МойКлиентскийМетод1С(Параметры);
Иначе
// Обработка неизвестного метода
Сообщить("Неизвестный метод 1С: " + ИмяМетода, СтатусСообщения.Важное);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
// Этот метод будет вызываться из JavaScript
Процедура МойКлиентскийМетод1С(Параметры) Экспорт
Сообщить("Метод 1С вызван из JavaScript!");
Сообщить("Переданы параметры: " + Параметры.Имя + ", возраст: " + Параметры.Возраст);
// Здесь можно выполнить любую необходимую логику 1С
КонецПроцедуры
В обработчике ПолеHTMLДокументаПриНажатии мы проверяем ИдентификаторЭлемента, чтобы убедиться, что нажатие произошло на нашем скрытом элементе. Затем мы получаем значение атрибута data-payload, которое содержит JSON-строку с именем метода и параметрами. Используя JSON.Прочитать(), мы преобразуем эту строку в структуру 1С и вызываем соответствующий клиентский метод формы. Важно, чтобы вызываемый метод был экспортным и помечен как &НаКлиенте.
Этот механизм обеспечивает надежный и контролируемый способ вызова методов 1С из JavaScript, обходя ограничения прямой передачи объектов.
Для взаимодействия в обратном направлении, когда 1С нужно вызвать функцию JavaScript или получить данные из HTML-документа, мы используем свойство Документ.defaultView поля HTML-документа. Объект defaultView предоставляет доступ к глобальному объекту window HTML-документа, через который мы можем вызывать определенные в JavaScript функции или обращаться к глобальным переменным.
В HTML-документе мы определяем JavaScript-функцию, которую хотим вызвать из 1С. Эта функция может принимать параметры и возвращать значение.
<!-- В вашем JavaScript-коде внутри HTML-документа -->
<script type="text/javascript">
// Функция, которую будет вызывать 1С
function getSum(a, b) {
console.log("JavaScript: Получены числа для сложения:", a, b);
return a + b;
}
// Функция, которая может изменить HTML-содержимое
function updateHtmlContent(message) {
var outputDiv = document.getElementById('output');
if (outputDiv) {
outputDiv.innerHTML = '<strong>Сообщение из 1С:</strong> ' + message;
}
}
</script>
<!-- В теле HTML, где-то для вывода -->
<div id="output"></div>
Из клиентского кода 1С мы можем вызвать эти JavaScript-функции. Важно, что все функции и глобальные переменные, определенные в глобальной области видимости HTML-документа (или доступные через window), будут доступны через Элементы.ПолеHTMLДокумента.Документ.DefaultView.
Пример кода 1С:
&НаКлиенте
Процедура ВызватьJavaScriptФункцию(Команда)
Если Элементы.ПолеHTMLДокумента.Документ.DefaultView.getSum Тогда
// Вызов функции getSum в JavaScript и получение результата
РезультатСложения = Элементы.ПолеHTMLДокумента.Документ.DefaultView.getSum(10, 20);
Сообщить("Результат сложения из JavaScript: " + РезультатСложения);
Иначе
Сообщить("Функция JavaScript 'getSum' не найдена или еще не загружена.", СтатусСообщения.Важное);
КонецЕсли;
Если Элементы.ПолеHTMLДокумента.Документ.DefaultView.updateHtmlContent Тогда
// Вызов функции updateHtmlContent для изменения содержимого HTML
Элементы.ПолеHTMLДокумента.Документ.DefaultView.updateHtmlContent("Привет из 1С!");
Иначе
Сообщить("Функция JavaScript 'updateHtmlContent' не найдена или еще не загружена.", СтатусСообщения.Важное);
КонецЕсли;
КонецПроцедуры
Таким образом, мы можем не только вызывать JavaScript-функции, но и передавать им параметры, а также получать возвращаемые значения, что открывает широкие возможности для динамического обновления содержимого HTML-поля или выполнения сложной логики на стороне клиента, например, когда требуется маршрутизация Яндекс-карт в 1С.
Для успешной и эффективной реализации взаимодействия между полем HTML-документа и управляемой формой 1С, рассмотрим несколько важных моментов и рекомендаций:
ДокументСформирован.
Как показано в примерах, очень важно выполнять инициализацию или начинать взаимодействие с HTML-додокументом только после того, как он полностью загружен и его объектная модель готова к работе. Для этого используйте обработчик события ПолеHTMLДокументаДокументСформирован. Этот обработчик срабатывает, когда HTML-документ успешно загружен в поле.
&НаКлиенте
Процедура ПолеHTMLДокументаДокументСформирован(Элемент)
// Здесь ваш код для инициализации или первого взаимодействия
// Например, можно вызвать JavaScript-функцию, чтобы она зарегистрировала
// какие-либо обработчики или подготовила данные.
// Элементы.ПолеHTMLДокумента.Документ.DefaultView.initMyScript();
КонецПроцедуры
Для передачи сложных данных (объектов, структур, массивов) между 1С и JavaScript настоятельно рекомендуем использовать формат JSON (JavaScript Object Notation). JSON является стандартизированным, легко читаемым и легко парсируемым форматом как в JavaScript (через JSON.stringify() и JSON.parse()), так и в 1С (через объекты JSON.Записать() и JSON.Прочитать()).
Это обеспечивает надежную и унифицированную передачу информации, предотвращая проблемы с кодировкой или сериализацией нестандартных объектов.
&НаКлиенте.
Все операции по непосредственному взаимодействию с полем HTML-документа (такие как вызов JavaScript-функций, чтение атрибутов, обработка нажатий) должны выполняться в клиентском контексте 1С. Убедитесь, что ваш код помечен директивой &НаКлиенте.
Платформа 1С:Предприятие обладает богатым набором стандартных элементов управляемой формы. Поле HTML-документа следует использовать только в тех случаях, когда стандартные элементы не позволяют решить задачу, например, для отображения сложного интерактивного контента, пользовательских инструкций с богатым форматированием, встроенной справки или интеграции со сторонними веб-компонентами (например, карты, графики, редакторы WYSIWYG).
Если взаимодействие требует обращения к серверной логике 1С, которая не может быть выполнена на клиенте (например, запись в базу данных, выполнение запросов, работа с тяжелыми данными), рассмотрите возможность использования HTTP-сервисов 1С. Из JavaScript можно отправлять HTTP-запросы на опубликованные HTTP-сервисы 1С, которые будут выполнять необходимую серверную обработку и возвращать результат, также часто в формате JSON.
Таким образом, хотя прямой подход к передаче объекта формы больше не работает, современные механизмы взаимодействия предоставляют гибкие и безопасные способы для построения полноценной двусторонней связи между полем HTML-документа и управляемой формой 1С. Используя описанные подходы, вы сможете успешно интегрировать веб-технологии в ваши решения на платформе 1С:Предприятие.