Как вызывать методы 1С из JavaScript в поле HTML-документа управляемой формы?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с платформой 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С, которые привели к такому поведению:

  1. Переход на Webkit (Chromium). Начиная с версии платформы 8.3.14.1565, 1С отказалась от использования движка Internet Explorer для отображения HTML-документов в пользу Webkit (на основе Chromium). Этот переход кардинально изменил объектную модель документа (DOM) и механизмы взаимодействия с внешним окружением. То, что работало в среде Internet Explorer, может не работать или работать по-другому в Webkit.
  2. Изоляция и безопасность. Поле HTML-документа стало гораздо более изолированным от контекста 1С из соображений безопасности. Прямая передача ссылок на объекты 1С могла представлять потенциальную уязвимость, позволяя вредоносному JavaScript-коду получить несанкционированный доступ к функциональности платформы. Разработчики 1С усилили "песочницу" для HTML-поля, что ограничивает прямой доступ к объектам вне его контекста.
  3. Изменение типа объекта. Свойство Документ у ПолеHTMLДокумента изменило свой тип. Ранее оно могло быть COMОбъект, что позволяло более глубокую интеграцию. Теперь оно часто возвращает ВнешнийОбъект, который имеет более ограниченный набор методов и свойств для взаимодействия, направленный на управляемый обмен данными, а не на прямую передачу объектов.

Таким образом, старый подход, основанный на прямой передаче объекта формы, стал неактуальным и небезопасным. Нам потребуется использовать новые, более структурированные и контролируемые механизмы для организации взаимодействия.

Современные подходы к взаимодействию: двусторонняя связь

Несмотря на усиление изоляции, возможности двустороннего взаимодействия между полем HTML-документа и управляемой формой 1С остались, но они реализуются по-другому. Мы рассмотрим два основных метода:

  1. Вызов методов 1С из JavaScript с помощью скрытых HTML-элементов и события «ПриНажатии».
  2. Обращение к JavaScript-функциям из 1С и чтение результатов (т.е. вызов функций JavaScript из 1С).

Эти подходы позволяют безопасно и контролируемо обмениваться данными и вызывать нужные функции с обеих сторон (например, когда внедряются Яндекс-карты в 1С).

Решение 1: Вызов методов 1С из JavaScript с помощью скрытых HTML-элементов и события «ПриНажатии»

Этот метод является одним из наиболее распространенных и надежных для инициирования вызова методов 1С из JavaScript. Он основан на имитации пользовательского действия и использовании события ПриНажатии поля HTML-документа.

Разберем по шагам, как это работает:

  1. Создание скрытого HTML-элемента в HTML-документе.

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

    Например, мы можем использовать скрытый div или input type="hidden":

    
    <!-- В вашем HTML-документе -->
    <div id="externalFormCaller" style="display: none;"></div>
    

    Этот элемент div с идентификатором externalFormCaller будет нашим посредником. Важно, чтобы он был скрыт с помощью display: none; или visibility: hidden;.

  2. Подготовка JavaScript-функции для вызова 1С.

    Когда нам нужно вызвать метод 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 на этом элементе.

  3. Обработка события «ПриНажатии» в 1С.

    В управляемой форме 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, обходя ограничения прямой передачи объектов.

Решение 2: Обращение к JavaScript-функциям из 1С и чтение результатов (вызов из 1С в JS)

Для взаимодействия в обратном направлении, когда 1С нужно вызвать функцию JavaScript или получить данные из HTML-документа, мы используем свойство Документ.defaultView поля HTML-документа. Объект defaultView предоставляет доступ к глобальному объекту window HTML-документа, через который мы можем вызывать определенные в JavaScript функции или обращаться к глобальным переменным.

Рассмотрим, как это реализуется:

  1. Определение JavaScript-функции в HTML.

    В 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>
    
  2. Вызов JavaScript-функции из 1С.

    Из клиентского кода 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С, рассмотрим несколько важных моментов и рекомендаций:

  1. Использование события ДокументСформирован.

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

    
    &НаКлиенте
    Процедура ПолеHTMLДокументаДокументСформирован(Элемент)
        // Здесь ваш код для инициализации или первого взаимодействия
        // Например, можно вызвать JavaScript-функцию, чтобы она зарегистрировала
        // какие-либо обработчики или подготовила данные.
        // Элементы.ПолеHTMLДокумента.Документ.DefaultView.initMyScript();
    КонецПроцедуры
    
  2. Передача данных в формате JSON.

    Для передачи сложных данных (объектов, структур, массивов) между 1С и JavaScript настоятельно рекомендуем использовать формат JSON (JavaScript Object Notation). JSON является стандартизированным, легко читаемым и легко парсируемым форматом как в JavaScript (через JSON.stringify() и JSON.parse()), так и в 1С (через объекты JSON.Записать() и JSON.Прочитать()).

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

  3. Контекст выполнения &НаКлиенте.

    Все операции по непосредственному взаимодействию с полем HTML-документа (такие как вызов JavaScript-функций, чтение атрибутов, обработка нажатий) должны выполняться в клиентском контексте 1С. Убедитесь, что ваш код помечен директивой &НаКлиенте.

  4. Целесообразность использования поля HTML-документа.

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

  5. HTTP-сервисы для сложной серверной логики.

    Если взаимодействие требует обращения к серверной логике 1С, которая не может быть выполнена на клиенте (например, запись в базу данных, выполнение запросов, работа с тяжелыми данными), рассмотрите возможность использования HTTP-сервисов 1С. Из JavaScript можно отправлять HTTP-запросы на опубликованные HTTP-сервисы 1С, которые будут выполнять необходимую серверную обработку и возвращать результат, также часто в формате JSON.

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

← На главную