Бесконечный цикл для tag-it, завернутый в выбивающий компонент

Я создал нокаутированную пользовательскую привязку, чтобы обернуть тег-it по предложению Droyad. Окончательный код (упрощенный):

ko.bindingHandlers.tagit = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var bind = function () {
            valueAccessor().tagsList($(element).tagit("assignedTags"));
        };

        var options = $.extend({
            afterTagAdded: bind,
            afterTagRemoved: bind
        }, valueAccessor().options || {});

        // Create tags editor
        $(element).tagit(options);

        ////// Block 1
        var value = ko.utils.unwrapObservable(valueAccessor());
        var tags = value.tagsList();
        for(var x = 0; x < tags.length; x++) {
            $(element).tagit("createTag", tags[x]);
        }
        ////// End Block 1
    },
    ////// Block 2
    update: function (element, valueAccessor, allBindingsAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var tags = value.tagsList();
        $(element).tagit("removeAll");
        for(var x = 0; x < tags.length; x++) {
            $(element).tagit("createTag", tags[x]);
        }
    }
    ////// End Block 2
};

Соответствующий HTML-код:

<div data-bind="with: currentDocument">
  <input data-bind="tagit: {tagsList: tags}"></input>
</div>

Моя проблема: я должен использовать "Блок 1" и удалить "Блок 2", в противном случае компонент входит в бесконечный цикл. Без блока 2 тег-он отображает теги каждый раз, когда я изменяю документ (изменения currentDocument), и я могу редактировать теги вручную без проблем. Вместо этого, если я изменю currentDocument.tags программно, это изменение не визуализируется (очевидно). Если я удаляю блок 1 и добавляю блок 2, обратный вызов afterTagAdded запускается для каждого добавленного тега, который, в свою очередь, изменяет массив тегов, который запускает функцию обновления и так далее.

Есть идеи, как решить проблему? Я думаю, что обратные вызовы afterTagAdded и afterTagRemoved срабатывают только для ручных модификаций, а не для $(element).tagit("createTag", tags[x]); проблема может быть решена. Спасибо за вашу помощь!

1 ответ

Решение простое, хотя и не элегантное. Я определил переменную "loading", которая имеет значение true, если изменение вызвано загрузкой редактора тегов. Когда true блокирует наблюдаемое обновление. (В предыдущем коде удалите блок 1 и добавьте блок 2).

Попытка объяснить проблему на SO, как обычно, помогает мне найти решение. Спасибо также за это!

ko.bindingHandlers.tagit = {
    loading: false,
    init: function (element, valueAccessor, allBindingsAccessor) {
        var bind = function () {
            if(ko.bindingHandlers.tagit.loading) return;
            valueAccessor().tagsList($(element).tagit("assignedTags"));
        };
        ...
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        // Load data
        ko.bindingHandlers.tagit.loading = true;
        var value = ko.utils.unwrapObservable(valueAccessor());
        var tags = value.tagsList();
        $(element).tagit("removeAll");
        for(var x = 0; x < tags.length; x++) {
            $(element).tagit("createTag", tags[x]);
        }
        ko.bindingHandlers.tagit.loading = false;
    }
Другие вопросы по тегам