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">&#10005; Удалить</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);