8.7.2.5. Вариант 5. Создание нового компонента¶
На текущую форму «Заявка на закуп» добавлен компонент «Пользовательский компонент». В его настройках значением выбран такой пользовательский компонент, который позволяет выбрать поставщика и посмотреть о нем подробную информацию. HTML и JavaScript коды такого пользовательского компонента приведены ниже. Список доступных действий:
- выбор записи реестра поставщиков из диалогового окна с помощью кликабельного лейбла Выбрать из реестра (доступен всегда), в котором столбцы - это отображаемые поля реестра;
- ручной ввод и подбор результатов среди записей реестра поставщиков (поиск производится по всем полям);
- значения в выпадающем списке составлены из полей диалога (т.е. отображаемых полей реестра), разделенных тире;
- выбранное значение компонента меняет его внешний вид: поле ввода заменяется на подчеркнутый и кликабельный лейбл, составленный из значащего содержимого этого реестра;
- по нажатию на выбранную запись происходит открытие в диалоговом окне проигрывателя формы, который отображает эту запись из реестра поставщиков в режиме просмотра;
- создание новой записи в реестре поставщиков прямо из текущей формы с помощью кликабельного лейбла +Создать (доступен всегда): проигрыватель формы в режиме редактирования открывается в диалоговом окне;
- удаление текущего значения компонента с помощью кликабельного лейбла х Удалить (доступен только в случае, когда в компоненте выбрано какое-либо значение): компонент очищается и снова принимает вид поля ввода.
Исходный код JavaScript и CSS формы аналогичны Вариант 1. Отображение проигрывателя, встроенного во внешний портал.
HTML код пользовательского компонента:
<div innerId="textView" style="text-decoration:underline; cursor:pointer;width:calc(100% ); margin-bottom:2px"></div>
<input type="text" class="asf-textBox" innerId="name" style="width:calc(100% )"/>
<div style="color:#606060; text-decoration:underline" class="asf-InlineBlock asf-cursorPointer" innerId="add">+Создать</div>
<div style="color:#606060; margin-left:10px; text-decoration:underline" class="asf-InlineBlock asf-cursorPointer" innerId="browse">Выбрать из реестра</div>
<div style="color:#606060; margin-left:10px; text-decoration:underline" class="asf-InlineBlock asf-cursorPointer" innerId="delete">✕ Удалить</div>
JavaScript код пользовательского компонента:
/* инициализация модели */
/**
* текстовое значение записи реестра
* @type {string}
*/
model.textValue = "";
/**
* идентификатор файла по форме выбранной записи реестра
* @type {string}
*/
model.asfDataId = null;
/**
* метод должен возвращать идентификатор реестра, можно переопределить в скрипте пользовательского компонента
* @returns {string}
*/
if (!model.getRegistryID) {
model.getRegistryID = function () {
return "d67afba7-8f16-4f7e-a920-1eceb694f646";
};
}
/**
* обновить текстовое представление записи реестра
*/
model.updateTextView = function () {
if (!model.getValue()) {
model.textValue = "";
model.asfDataId = null;
model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
return;
}
AS.FORMS.ApiUtils.getAsfDataUUID(model.getValue(), function (newAsfDataId) {
model.asfDataId = newAsfDataId;
AS.FORMS.ApiUtils.getDocMeaningContent(model.getRegistryID(), newAsfDataId, function (text) {
model.textValue = text;
model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
});
});
};
/**
* получить тестовое представление записи реестра
* @returns {string|string|*}
*/
model.getTextValue = function () {
return model.textValue;
};
// подписываемся на событие модели об изменении содержания, чтобы подгрузить дополнительные данные
model.on(AS.FORMS.EVENT_TYPE.valueChange, function () {
model.updateTextView();
});
/**
* метод реализовывает вставку asfData
* @param asfData
*/
model.setAsfData = function (asfData) {
model.setValue(asfData.key);
};
/**
* метод реализовывает получение данных компонента для сохранения
* @param blockNumber
* @returns {*}
*/
model.getAsfData = function (blockNumber) {
return AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber, model.textValue, model.value);
};
/* инициализация отображения */
/**
* реестр
* @type {object}
*/
var registry = null;
/**
* видимые колонки реестра
* @type {Array}
*/
var registryColumns = [];
/**
* поле ввода для поиска записей реестра
* @type {XMLList|*}
*/
var input = jQuery(view.container).children("[innerId='name']");
/**
* поле для отображения выбранной записи реестра
* @type {XMLList|*}
*/
var textView = jQuery(view.container).children("[innerId='textView']");
/**
* кнопка добавления записи
* @type {XMLList|*}
*/
var addIcon = jQuery(view.container).children("[innerId='add']");
/**
* кнопка выбора записи из реестра
* @type {XMLList|*}
*/
var browseIcon = jQuery(view.container).children("[innerId='browse']");
/**
* кнопка удаления текущей выбранной записи
* @type {XMLList|*}
*/
var deleteIcon = jQuery(view.container).children("[innerId='delete']");
// кнопку удаления текущей выбраннйо записи скрываем
deleteIcon.hide();
// по нажатию на кнопку "выбрать из реестра" открываем стандратный диалог выбра записи реестра
browseIcon.click(function () {
AS.SERVICES.showRegisterLinkDialog(registry, function (documentId) {
model.setValue(documentId);
});
});
// по нажатию на кнопку "создать" открываем форму создания записи реестра
addIcon.click(function () {
if (!registry.rr_create) {
alert("У вас нет прав на создание записей данного реестра");
return;
}
var createPlayerDiv = jQuery("<div>");
createPlayerDiv.css("width", "800px");
createPlayerDiv.css("border", "1px solid #afafaf");
var saveButton = jQuery("<button>", {class: "ns-approveButton ns-basicChooserApplyButton"});
saveButton.button();
saveButton.html("Добавить поставщика");
saveButton.css("margin", "auto");
saveButton.css("display", "block");
var player = AS.FORMS.createPlayer();
player.view.setEditable(true);
player.showFormData(registry.formId);
player.view.appendTo(createPlayerDiv);
createPlayerDiv.append(saveButton);
createPlayerDiv.dialog({
width: 670,
height: 400,
modal: true
});
saveButton.click(function () {
var valid = player.model.isValid();
if (!valid) {
alert("Введите все обязательные поля");
return;
}
AS.SERVICES.showWaitWindow();
AS.FORMS.ApiUtils.simpleAsyncGet("rest/api/registry/create_doc?registryID=" + registry.registryID, function (result) {
if (result.errorCode != 0) {
AS.SERVICES.hideWaitWindow();
alert("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору");
return;
}
player.model.asfDataId = result.dataUUID;
player.saveFormData(function (result) {
AS.SERVICES.hideWaitWindow();
if (_.isUndefined(result)) {
alert("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору");
return;
}
createPlayerDiv.dialog("destroy");
AS.FORMS.ApiUtils.getDocumentIdentifier(result, function (documentID) {
model.setValue(documentID);
});
});
});
});
});
// по нажатию на кнопку удалить - удаляем выбранное значение
deleteIcon.click(function () {
model.setValue(null);
});
// по нажатию на текстовое отображение - открываем запись реестра на просмотр
textView.click(function () {
var createPlayerDiv = jQuery("<div>");
createPlayerDiv.css("width", "800px");
createPlayerDiv.css("border", "1px solid #afafaf");
var player = AS.FORMS.createPlayer();
player.view.setEditable(false);
player.showFormData(null, null, model.asfDataId, 0);
player.view.appendTo(createPlayerDiv);
createPlayerDiv.dialog({
width: 1000,
height: 330,
modal: true
});
});
// скрываем или отображаем инпуты в зависимости от того режим чтения это или редактирования
if (editable) {
textView.hide();
} else {
input.hide();
addIcon.hide();
browseIcon.hide();
deleteIcon.hide();
}
// релизовываем метод обновления отображения согласно изменившимся данным модели
view.updateValueFromModel = function () {
input.val("");
if (model.getValue()) {
textView.css("display", "");
input.hide();
textView.html(model.getTextValue());
input.hide();
if (editable) {
deleteIcon.css("display", "");
}
} else {
if (editable) {
textView.hide();
input.css("display", "");
} else {
textView.css("display", "");
input.hide();
}
textView.html("");
input.text("");
deleteIcon.hide();
}
};
// подписываем на событие подгрузки дополнительных данных значения
model.on(AS.FORMS.EVENT_TYPE.dataLoad, function () {
view.updateValueFromModel();
});
/**
* если нет прав создания записи реестра, то кнопки создать не должно быть видно
*/
function validateIconsState() {
addIcon.hide();
if (registry.rr_create) {
addIcon.css("display", "");
}
}
/**
* инициализируем компонент (получаем реестр, колонки)
*/
function initComponent() {
if (!model.getRegistryID()) {
return;
}
AS.FORMS.ApiUtils.getRegistry(model.getRegistryID(), function (reg) {
registry = reg;
registry.registryID = model.getRegistryID();
registryColumns = [];
registry.columns.forEach(function (col) {
if (col.visible != 1) {
return;
}
registryColumns.push(col);
});
registryColumns = registryColumns.sort(function (item1, item2) {
var number1 = item1.order;
var number2 = item2.order;
if (number1 === number2) {
if (item1.name < item2.name) {
return -1;
} else if (item1.name > item2.name) {
return 1;
}
} else {
if (number1 === 0) {
return 1;
} else if (number2 === 0) {
return -1;
} else if (number1 < number2) {
return -1;
} else {
return 1;
}
}
return 0;
});
validateIconsState();
});
}
// при вводе пользователя отображаем первые 20 результатов поиска
input.on("input", function () {
var search = input.val();
if (search.length === 0 || !registry) {
AS.SERVICES.showDropDown([]);
return;
}
AS.FORMS.ApiUtils.getRegistryData(model.getRegistryID(), 0, 10, search, null, null, function (foundData) {
var values = [];
foundData.result.forEach(function (record) {
var value = {value: record.documentID};
var label = "";
registryColumns.forEach(function (column) {
label += record.fieldValue[column.columnID] + " - ";
});
value.title = label;
values.push(value);
});
AS.SERVICES.showDropDown(values, input, null, function (selectedValue) {
model.setValue(selectedValue);
view.updateValueFromModel();
});
});
});
setTimeout(function () {
initComponent();
}, 0);