1

Это настраиваемая привязка для нокаута, которую я написал с помощью поля типа BootStrap. Все работает, как ожидалось, но единственный вопрос, который я имею, что всякий раз, когда я очищаю мое поле нокаут наблюдаемого еще содержит последнее действительное selection.Not уверено, что я делаю неправильно ..Пользовательский привязку нокаута с бутстрапом Проблема с типом с пустыми значениями

ko.bindingHandlers.productTypeahead = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) 
     { 
     var root = bindingContext.$root; 

     var options = ko.unwrap(valueAccessor()) || {}, 
       $el = $(element); 

     options.source = _.debounce(function (query, process) { 
      root.api.SearchProducts(query) 
        .done(function (data) { 
         process(data); 
        }).fail(function (xhr) { 
         root._alert.error("Could not search products - " + JSON.parse(xhr.responseText).ExceptionMessage); 
        }); 
       } , 300); 

     $el.attr("autocomplete", "off") 
      .typeahead({ 
       source: options.source, 
       autoSelect: true, 
       displayText: function (item) { return item != null ? item.id : ""; }, 
       matcher: function() { return true; },// api does this already 
       items: 15, 
       minLength: 3, 
       updater: function (item) { 
        options.value(item); 
       }, 
       highlighter: function (item) { 
        var query = this.query; 
        query = query.replace(/[^\w\']+/g, "|"); 
        var queryRegex = new RegExp("\\b(" + query + ")", "gi"); 
        return item.replace(queryRegex, "<strong>$1</strong>"); 
       } 
      }); 

     // if KO removes the element via templating, then destroy the typeahead 
     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $el.typeahead("destroy"); 
      $el = null; 
     }); 
    } 
}; 

ответ

2

Вы могли бы использовать input событие для обработки этого случая. Код ниже проверяет только на value === "", вы можете обнаружить, что более эффективная проверка работает лучше в вашем приложении.

Также обратите внимание на измененный обработчик ошибок - вы никогда не должны разбирать JSON без блока try/catch.

ko.bindingHandlers.productTypeahead = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var root = bindingContext.$root; 
     var options = ko.unwrap(valueAccessor()) || {}; 

     options.source = _.debounce(function (query, process) { 
      root.api.SearchProducts(query) 
       .done(process).fail(function (xhr) { 
        var responseData; 
        try { 
         responseData = JSON.parse(xhr.responseText); 
         root._alert.error("Could not search products - " + responseData.ExceptionMessage); 
        } catch (ex) { 
         root._alert.error("Unexpected response: " + xhr.responseText); 
        } 
       }); 
     } , 300); 

     $(element).attr("autocomplete", "off") 
      .typeahead({ 
       source: options.source, 
       autoSelect: true, 
       displayText: function (item) { return item !== null ? item.id : ""; }, 
       matcher: function() { return true; },// api does this already 
       items: 15, 
       minLength: 3, 
       // you can use observables as callbacks directly 
       updater: options.value, 
       highlighter: function (item) { 
        var query = this.query.replace(/[^\w']+/g, "|"); 
        var queryRegex = new RegExp("\\b(" + query + ")", "gi"); 
        return item.replace(queryRegex, "<strong>$1</strong>"); 
       } 
      }).on("input", function() { 
       if (this.value === "") { 
        options.value(""); 
       } 
      }); 

     // if KO removes the element via templating, then destroy the typeahead 
     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $(element).typeahead("destroy"); 
     }); 
    } 
};