Ошибка Нельзя изменять поле содержащее объект данных формы в 1С

В процессе разработки на платформе 1С:Предприятие начинающие программисты могут столкнуться с ошибкой: “Нельзя изменять поле, содержащее объект данных формы”. Эта ошибка возникает при попытке изменить реквизит формы, связанный с данными формы. Давайте разберёмся, почему это происходит и как избежать подобных ситуаций.

Причина ошибки

Когда мы пытаемся передать с клиента на сервер реквизит, в котором содержатся данные формы, либо когда мы пытаемся изменить такой реквизит – мы получим ошибку “Нельзя изменять поле содержащее объект данных формы”.
Давайте воспроизведем ошибку. Создадим внешнюю обработку, добавим в нее реквизит ТаблицаКонтрагенты  с типом “Таблица значений”. И добавим команду, в которой напишем:

&НаКлиенте
Процедура ВоспроизвестиОшибку(Команда)
	ТаблицаКонтрагенты = Новый СписокЗначений;
КонецПроцедуры

Второй пример. В этой же обработке добавим еще одну команду, и в ее обработчиках напишем следующее:

&НаСервере
Процедура ВоспроизвестиОшибкуПриПередачеНаСерверНаСервере(Объект)
	// Вставить содержимое обработчика.
КонецПроцедуры

&НаКлиенте
Процедура ВоспроизвестиОшибкуПриПередачеНаСервер(Команда)
	ВоспроизвестиОшибкуПриПередачеНаСерверНаСервере(Объект);
КонецПроцедуры

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

&НаСервере
Процедура ВоспроизвестиОшибкуНаСторонеСервераНаСервере()
	ТаблицаКонтрагенты = Новый ТаблицаЗначений;
КонецПроцедуры

&НаКлиенте
Процедура ВоспроизвестиОшибкуНаСторонеСервера(Команда)
	ВоспроизвестиОшибкуНаСторонеСервераНаСервере();
КонецПроцедуры

Как исправить ошибку "Нельзя изменять поле содержащее объект данных формы"?

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

Экранирование контекста при помощи локальной переменной. В этом случае мы будем работать не с реквизитом формы, а с переменной с таким же именем. Важно помнить, что на самом деле когда мы пишем напрямую имя реквизита формы, это эквивалентно записи ЭтаФорма.ИмяРеквизита или ЭтотОбъект.ИмяРеквизита.

&НаКлиенте
Процедура ИсправитьОшибку(Команда)
	Перем ТаблицаКонтрагенты;
	ТаблицаКонтрагенты = Новый СписокЗначений;
КонецПроцедуры

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

&НаСервере
Процедура ИсправитьОшибку2НаСервере(Знач Объект)
	// Вставить содержимое обработчика.
КонецПроцедуры

&НаКлиенте
Процедура ИсправитьОшибку2(Команда)
	ИсправитьОшибку2НаСервере(Объект);
КонецПроцедуры

Вместо изменения реквизита можно работать с его копией. Например:

&НаСервере
Процедура ИсправитьОшибку3НаСервере()
	
	// вариант 1
	КопияТаблицаКонтрагенты = ТаблицаКонтрагенты.Выгрузить();
	// вариант 2
	КопияТаблицаКонтрагенты = РеквизитФормыВЗначение("ТаблицаКонтрагенты");
	// вариант 3
	КопияТаблицаКонтрагенты = ДанныеФормыВЗначение(ТаблицаКонтрагенты,Тип("ТаблицаЗначений"));
КонецПроцедуры

&НаКлиенте
Процедура ИсправитьОшибку3(Команда)
	ИсправитьОшибку3НаСервере();
КонецПроцедуры

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

&НаСервереБезКонтекста
Процедура ИсправитьОшибку4НаСервере()
	ТаблицаКонтрагенты = Новый ТаблицаЗначений;
КонецПроцедуры

&НаКлиенте
Процедура ИсправитьОшибку4(Команда)
	ИсправитьОшибку4НаСервере();
КонецПроцедуры

Так что же все-таки за данные формы, и зачем они нужны? Если остались силы на немного теории – читайте ниже.

Что такое объект данных формы?

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

К этим объектам относятся все реквизиты формы с типом значения начинающиеся с “ДанныеФормы”. Рассмотрим их вкратце:

ДанныеФормыСтруктура — это объект, который хранит набор свойств произвольного типа. Каждое свойство может быть как простым значением, так и сложным объектом: другой структурой, коллекцией или структурой с коллекцией. Например, в форме справочника объект может быть представлен именно таким типом данных.

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

ДанныеФормыСтруктураСКоллекцией — это объект, который объединяет в себе свойства структуры и коллекции. С ним можно работать как со структурой (по ключам) или как с коллекцией (по индексам). Например, набор записей в форме может быть представлен именно этим типом данных.

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

Прикладной объект в форме может быть представлен одним или несколькими элементами данных. Например, документ, содержащий табличную часть, будет представлен объектом типа ДанныеФормыСтруктура (основные данные документа), которому подчинен объект типа ДанныеФормыКоллекция (табличная часть документа).

Итак, мы разобрали ошибку “Нельзя изменять поле содержащее объект данных формы” и основные варианты ее исправления.

Оставьте комментарий

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

семнадцать + 20 =

К НАЧАЛУ