В работе с таблицей одной из полезных функций выступает перенос строки в таблице. На текущий момент стандартный функционал переноса строки в таблице отсутствует.
В статье предлагается использовать виджет Кнопка и виджет Модальное окно. При нажатии на кнопку отобразится модальное окно, в котором пользователю нужно указать номер переносимой строки и новый номер строки (место вставки строки). В модальном окне также есть ещё один виджет Кнопка, который используется для запуска сценария переноса строки в таблице.
Идея сценария переноса строки проста. В указанное пользователем место в таблице (новый номер строки) вставляется пустая строка. Затем в пустую строку копируются значения из переносимой строки. После копирования переносимая строка удалятся из таблицы.
Ниже представлен видео-пример.
Подготовка.
1. Создадим произвольное приложение. Откроем меню приложения. Выберем пункт Настройка формы. Перейдем в Расширенный режим.
2. На вкладке Контекст добавим свойство типа Таблица.
3. Произведём настройки таблицы. Для удобства ставим галочку Отображать порядковый номер в начале строки.
Примечание: колонка Позиция номенклатуры имеет тип Приложение (один) и ссылается на приложение Склад.
4. Сохраняем настройки полей и приложения.
Реализация.
1. Вернёмся в расширенный режим редактирования приложения и создадим свою форму, например, форму создания. Её в дальнейшем можно использовать и для редактирования элемента приложения.
2. Удалим виджет Стандартная форма элемента с рабочей области.
3. Вынесем на рабочую область созданное ранее свойство типа Таблица.
4. Вынесем на форму виджет Кнопка. После клика на кнопку система будет отображать виджет Модальное окно. Событие при нажатии openModalWindow.
5. Перейдем на вкладку Контекст и добавим на форму создания свойство Показать модальное окно (show_modal_window) c с типом Выбор «да/нет». Свойство будет использоваться для отображения модального окна.
6. На вкладке Контекст также добавим свойства:
a. Начальная позиция (start_position) с типом Число (Целое) и подсказкой Номер строки, которую требуется перенести,
b. Конечная позиция (end_position) с типом Число (Целое) и подсказкой Новый номер строки.
7. Вернемся на вкладку Шаблон и вынесем на рабочую область виджет Модальное окно. В настройках виджета Модальное окно свяжем настройку Показать окно с контекстной переменной формы Показать модальное окно.
8. В центральную область виджета Модальное окно добавим созданные контекстные свойства формы: Начальная позиция, Конечная позиция. При добавлении в настройках контекстных свойств формы можно связать настройку Обязательное поле с контекстной переменной формы Показать модальное окно.
9. В нижнюю часть виджета Модальное окно вынесем виджет Кнопка. После нажатия на эту кнопку произойдет запуск сценария с переносом строки. Событие при нажатии moveLine.
В итоге на рабочей области должно получиться примерно следующее:
10. Перейдем на вкладку Сценарии и добавим скрипты openModalWindow и moveLine.
Код:
async function openModalWindow(): Promise<void> {
// Отображаем модальное окно
ViewContext.data.show_modal_window = true;
// Очищаем значения в контекстных переменных формы
ViewContext.data.start_position = undefined;
ViewContext.data.end_position = undefined;
}
Код:
async function moveLine(): Promise<void> {
// Проверяем наличие данных в таблице
if (Context.data.table) {
// Проверяем наличие значение в контекстных переменных формы
if (ViewContext.data.start_position && ViewContext.data.end_position) {
// Проверяем какое из значений контекстных переменных формы больше
if (ViewContext.data.start_position < ViewContext.data.end_position) {
// Вставляем пустую строку в нужное место таблицы
const row = Context.data.table.insert(ViewContext.data.end_position);
// Заполняем новую строку путём копирования данных из переносимой строки
row.user = Context.data.table[ViewContext.data.start_position - 1].user;
row.phone_number = Context.data.table[ViewContext.data.start_position - 1].phone_number;
row.nomenclature = Context.data.table[ViewContext.data.start_position - 1].nomenclature;
row.amount = Context.data.table[ViewContext.data.start_position - 1].amount;
row.condition = Context.data.table[ViewContext.data.start_position - 1].condition;
// Удаляем неактуальную строку
Context.data.table.delete(ViewContext.data.start_position - 1);
}
else if (ViewContext.data.start_position > ViewContext.data.end_position) {
// Вставляем пустую строку в нужное место таблицы
const row = Context.data.table.insert(ViewContext.data.end_position - 1);
// Заполняем новую строку путём копирования данных из переносимой строки
row.user = Context.data.table[ViewContext.data.start_position].user;
row.phone_number = Context.data.table[ViewContext.data.start_position].phone_number;
row.nomenclature = Context.data.table[ViewContext.data.start_position].nomenclature;
row.amount = Context.data.table[ViewContext.data.start_position].amount;
row.condition = Context.data.table[ViewContext.data.start_position].condition;
// Удаляем неактуальную строку
Context.data.table.delete(ViewContext.data.start_position);
}
// Сохраняем изменения, которые произошли с таблицей
Context.data.table = Context.data.table;
// Прекращаем отображать модальное окно
ViewContext.data.show_modal_window = false;
}
}
}
11. Сохраняем и опубликовываем форму.
Сам функционал готов. Далее можно его доработать сделав более дружелюбным и понятным для конечного пользователя.
Делаем более дружелюбную логику.
Ниже представлены несколько вариантов и кратко описаны способы реализации.
1 Вариант. Отображать кнопку Перенос строки на форме, когда в таблице более 1 строки. Если в таблице пусто или одна строка, то кнопку Перенос строки не отображать.
Кратко о способе реализации:
1. Создаем контекстную переменную формы с типом Выбор «да/нет».
2. В настройках виджета кнопки Перенос строки связываем видимость с созданной контекстной переменной формы.
3. Добавляем два сценария с проверкой наличия таблицы и числа строк:
а) один используем для инициализацию,
б) один используем на изменение таблицы.
Сценарии должны изменять значение логической переменной.
Сценарий для инициализацию.
Код:
async function onInit(): Promise<void>{
// Отображаем кнопку Перенос строки на форме, если в таблице более 1 строки
if (Context.data.table && Context.data.table.length > 1) {
ViewContext.data.show_button = true;
}
else {
ViewContext.data.show_button = false;
}
}
Сценарий на изменение таблицы. Не забудьте связать его на форме с самой таблицей.
Код:
async function changeTable(): Promise<void> {
// Отображаем кнопку Перенос строки на форме, если в таблице более 1 строки
if (Context.data.table && Context.data.table.length > 1) {
ViewContext.data.show_button = true;
}
else {
ViewContext.data.show_button = false;
}
}
2. Вариант. Отобразить информационное окно, если пользователь не заполнит одно из полей на модальном окне, но кликнет в модальном окне на кнопку Перенос строки. При наличии информационного окна таблица не изменяется.
Кратко о способе реализации:
1. Добавляем в виджет Модальное окно виджет Информационный блок.
2. Создаем контекстную переменную формы с типом Выбор «да/нет».
3. Связываем контекстную переменную формы и с настройками видимости виджета Информационный блок.
4. Добавляем в сценарии openModalWindow и moveLine код на изменение логической переменной.
Код:
async function openModalWindow(): Promise<void> {
// Код написанный ранее
// НАДСТРОЙКИ
// Скрываем информационный блок
ViewContext.data.show_infowindow = false;
}
Код:
async function moveLine(): Promise<void> {
// Проверяем наличие данных в таблице
if (Context.data.table) {
// Проверяем наличие значение в контекстных переменных формы
if (ViewContext.data.start_position && ViewContext.data.end_position) {
// ТУТ ЕСТЬ КОД, НАПИСАННЫЙ РАНЕЕ
else {
// НАДСТРОЙКИ
// Показываем информационный блок
ViewContext.data.show_infowindow = true;
// Автозакрытие информационного блока через 3 сек. Если планируется использовать автозакрытие, то необходимо вне функций написать: declare const window: any;
const timeoutID = window.setTimeout(() => {ViewContext.data.show_infowindow = false;}, 3000);
}
}
}
3 Вариант. Настроить валидацию значений контекстной переменной формы. Если пользователь указывает число < 1 или больше, чем количество строк в таблице, то перед пользователем появляется информационное окно. При наличии информационного окна таблица не изменяется.
Кратко о способе реализации:
1. Добавляем в виджет Модальное окно виджет Информационный блок.
2. Создаем контекстную переменную формы с типом Выбор «да/нет».
3. Связываем контекстную переменную формы и с настройками видимости виджета Информационный блок.
4. Создаем сценарий для контекстных переменных формы: Начальная позиция, Конечная позиция. Связываем этот сценарий с настройками на изменение контекстных переменных формы.
Примечание: можно добавить ещё одну контекстную переменную формы типа Строка. Эту переменную можно использовать для формирования текста информационного сообщения.
Примечание: также в скрипте moveLine нужно внести корректировку в условие
Код:
async function moveLine(): Promise<void> {
// Проверяем наличие данных в таблице
if (Context.data.table) {
// Проверяем наличие значение в контекстных переменных формы
if (ViewContext.data.start_position && ViewContext.data.end_position && ViewContext.data.show_validate_infowindow == false) {
// ТУТ ЕСТЬ КОД
}
Код:
async function changePosition(): Promise<void> {
ViewContext.data.show_validate_infowindow = false;
ViewContext.data.validate_message = "Диапазон допустимых номеров строк от 1 до " + Context.data.table!.length + "!";
if (ViewContext.data.start_position !== undefined) {
if (ViewContext.data.start_position < 1 ||
ViewContext.data.start_position > Context.data.table!.length)
{
ViewContext.data.show_validate_infowindow = true;
}
}
else {
if (ViewContext.data.start_position == 0) {
ViewContext.data.show_validate_infowindow = true;
}
}
if (ViewContext.data.end_position !== undefined) {
if (ViewContext.data.end_position < 1 ||
ViewContext.data.end_position > Context.data.table!.length)
{
ViewContext.data.show_validate_infowindow = true;
}
}
else {
if (ViewContext.data.end_position == 0) {
ViewContext.data.show_validate_infowindow = true;
}
}
}
Подробное пошаговое описание способов реализации перечисленных выше методов выходит за рамки темы статьи. Во вложении для любознательных приложил решение. Выполнял на Saas версии системы.