3.4.2. Пользовательский компонент Выбор и создание записи реестра¶
Данный пользовательский компонент расширяет функциональность компонента выбор записи реестра, добавив к нему следующие возможности:
- создание записи реестра;
- просмотр файла по форме в диалоге;
- удаление выбранного значения.
На форме компонент отображается следующим образом:
Html код компонента содержит следующий код:
<style>
.edit {
border: 1px solid black;
float: right;
background: url('light/images/buttons/dark.gray/edit.png') 50%;
width: 30px;
height: 22px;
background-repeat: no-repeat;
border-radius: 5px;
border-color: gray;
}
.edited{
background-color: #efefef;
}
</style>
//ссылка на документ реестра
<div style="text-decoration:underline; cursor:pointer;width:calc(100% ); color:#06f; margin-bottom:2px"
innerId="textView" ></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 код.
Данные компонента будут храниться в виде:
{
"id":"custom-zthfcc",
"type":"custom",
"value":"Услуга3",
"key":"c38e83a0-c065-4dec-a334-d32e63fcb0b4"
}
Здесь id - это идентификатор компонента, type - тип, value - значение, key - ключ компонента
За способ хранения данных компонента отвечает следующий кусок кода:
/**
* метод реализовывает получение данных компонента для хранения
* @param blockNumber
* @returns {*}
*/
model.getAsfData = function (blockNumber) {
return AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber, model.textValue, model.value);
};
Здесь в качестве value передаем параметр model.textValue, который обновляется каждый раз при изменении значения компонента:
/**
* обновить текстовое представление записи реестра
*/
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;
if(!registry) return;
AS.FORMS.ApiUtils.getDocMeaningContent(registry.registryID, newAsfDataId, function (text) {
if (text === null || text === '') {
model.textValue = i18n.tr('Документ');
} else {
model.textValue = text;
}
model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
});
});
};
Переопределяем метод setAsfData
модели, в данном случае в качестве значения выступает key
(ид документа выбранной записи).
/**
* метод реализовывает вставку asfData
* @param asfData
*/
model.setAsfData = function (asfData) {
model.setValue(asfData.key);
};
В скрипте компонента на форме необходимо прописать код реестра, записи которого будут выбраны либо созданы. Это указывается следующим образом:
В результате получим следующий компонент:
Полный javascript код компонента с комментариями:
/**
* обновить текстовое представление записи реестра
*/
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(registry.registryID, newAsfDataId, function (text) {
if (text === null || text === '') {
model.textValue = i18n.tr('Документ');
} else {
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", "1000px");
createPlayerDiv.css("height", "700px");
createPlayerDiv.css("border", "1px solid #afafaf");
var saveButton = jQuery("<button>", {class: "ns-approveButton ns-basicChooserApplyButton"});
saveButton.button();
saveButton.html(i18n.tr("Создать"));
saveButton.css("margin", "auto");
saveButton.css("display", "block");
saveButton.css("margin-top", "10px");
saveButton.css("margin-bottom", "10px");
var player = AS.FORMS.createPlayer();
player.view.setEditable(true);
player.showFormData(registry.formId);
player.view.appendTo(createPlayerDiv);
player.model.on(AS.FORMS.EVENT_TYPE.dataLoad, function () {
console.log(player.model);
var registryModel = null;
if (player.model.formCode === 'crm_form_contact') {
registryModel = player.model.getModelWithId('crm_form_contact_lead_lead', 'crm_form_contact_lead');
}
if (player.model.formCode === 'crm_form_account') {
registryModel = player.model.getModelWithId('crm_form_account_lead_lead', 'crm_form_account_lead');
}
if (player.model.formCode === 'crm_form_dealActivity') {
registryModel = player.model.getModelWithId('crm_form_dealActivity_main_deal');
}
if (player.model.formCode === 'crm_form_leadActivity') {
registryModel = player.model.getModelWithId('crm_form_leadActivity_main_lead');
}
if (registryModel != null) {
registryModel.setValue(AS.SERVICES.getParameterByName("document_identifier", window.location.href));
}
});
createPlayerDiv.append(saveButton);
createPlayerDiv.dialog({
width: 1000,
height: 700,
modal: true
});
saveButton.click(function () {
var valid = player.model.isValid();
if (!valid) {
alert(i18n.tr("Введите все обязательные поля"));
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(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
return;
}
player.model.asfDataId = result.dataUUID;
player.saveFormData(function (result) {
AS.SERVICES.hideWaitWindow();
if (_.isUndefined(result)) {
alert(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
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", "1000px");
createPlayerDiv.css("height", "700px");
var editButton = jQuery('<div class="edit"></div>');
var saveButton = jQuery("<button>", {class: "ns-approveButton ns-basicChooserApplyButton"});
saveButton.button();
saveButton.html(i18n.tr("Сохранить"));
saveButton.css("margin", "auto");
saveButton.css("display", "block");
saveButton.css("margin-top", "10px");
saveButton.css("margin-bottom", "10px");
if (registry.code == 'crm_registry_leadActivities' || registry.code == 'crm_registry_dealActivities') {
createPlayerDiv.append(editButton);
editButton.click(function () {
if (player.view.editable) {
player.view.setEditable(false);
editButton.removeClass('edited');
saveButton.hide();
} else {
player.view.setEditable(true);
editButton.addClass('edited');
saveButton.show();
}
});
}
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.append(saveButton);
saveButton.hide();
createPlayerDiv.dialog({
width: 1000,
height: 700,
modal: true
});
saveButton.click(function () {
var valid = player.model.isValid();
if (!valid) {
alert(i18n.tr("Введите все обязательные поля"));
return;
}
AS.SERVICES.showWaitWindow();
player.saveFormData(function (result) {
AS.SERVICES.hideWaitWindow();
if (_.isUndefined(result)) {
alert(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
return;
}
createPlayerDiv.dialog("destroy");
AS.FORMS.ApiUtils.getDocumentIdentifier(result, function (documentID) {
model.setValue(documentID);
});
});
});
});
// скрываем или отображаем поля ввода в зависимости от того режим чтения это или редактирования
if (!editable) {
input.hide();
addIcon.hide();
browseIcon.hide();
deleteIcon.hide();
}
addIcon.text('+' + i18n.tr('Создать'));
browseIcon.text(i18n.tr('Выбрать из реестра'));
deleteIcon.html('<div style="color:#606060; margin-left:10px; text-decoration:underline" ' +
'class="asf-InlineBlock asf-cursorPointer" innerId="delete">✕' + i18n.tr('Удалить') + '</div>');
// реализовываем метод обновления отображения согласно изменившимся данным модели
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 {
input.hide();
addIcon.hide();
browseIcon.hide();
deleteIcon.hide();
}
} else {
if (editable) {
input.css("display", "");
} else {
input.hide();
addIcon.hide();
browseIcon.hide();
deleteIcon.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 && editable) {
addIcon.css("display", "");
}
}
/**
* инициализируем компонент (получаем реестр, колонки)
*/
function initComponent() {
AS.FORMS.ApiUtils.simpleAsyncGet('rest/api/registry/info?code=' + model.code, function (reg) {
registry = reg;
registry.registryID = reg.registryID;
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;
});
model.updateTextView();
view.updateValueFromModel();
validateIconsState();
});
}
// при вводе пользователя отображаем первые 10 результатов поиска
input.on("input", function () {
var search = input.val();
if (search.length === 0 || !registry) {
AS.SERVICES.showDropDown([]);
return;
}
AS.FORMS.ApiUtils.getRegistryData(registry.registryID, 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) {
if (record.fieldValue[column.columnID] !== undefined) {
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);
AS.SERVICES.getParameterByName = function(name, url) {
if (!url) {
url = window.location.href;
}
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
};