2012-05-23 3 views
0

Я нашел образец на сайте knockoutjs. здесь они являются обязательными значениями в поле списка множественного выбора. Но они используют очень простой наблюдаемый массив. availableCountries и selectedCountries.knockoutjs сложный массив databind в нескольких списках выбора

<p> 
    Choose some countries you'd like to visit: 
    <select data-bind="options: availableCountries, selectedOptions: chosenCountries" size="5" multiple="true"></select> 
</p> 

<script type="text/javascript"> 
    var viewModel = { 
     availableCountries : ko.observableArray(['France', 'Germany', 'Spain']), 
     chosenCountries : ko.observableArray(['Germany']) // Initially, only Germany is selected 
    }; 

    // ... then later ... 
    viewModel.chosenCountries.push('France'); // Now France is selected too 
</script> 

Но моя модель слишком сложна и упоминает о части моей модели как формате json.

"JobOrderDelivTranscript" : [{ 
     "TranscriptType" : { 
      "Id" : 1, 
      "Name" : null, 
      "CreatedBy" : 0, 
      "CreatedDate" : "0001-01-01T00:00:00", 
      "ModifiedBy" : 0, 
      "ModifiedDate" : "0001-01-01T00:00:00", 
      "IsActive" : false, 
      "EntityStatus" : 0, 
      "ErrorMessage" : null, 
      "ExternalID" : 0, 
      "ExternalSystemID" : 0 
     }, 
     "Id" : 1, 
     "Name" : null, 
     "CreatedBy" : 0, 
     "CreatedDate" : "0001-01-01T00:00:00", 
     "ModifiedBy" : 0, 
     "ModifiedDate" : "0001-01-01T00:00:00", 
     "IsActive" : false, 
     "EntityStatus" : 0, 
     "ErrorMessage" : null, 
     "ExternalID" : 0, 
     "ExternalSystemID" : 0 
    }, { 
     "TranscriptType" : { 
      "Id" : 2, 
      "Name" : null, 
      "CreatedBy" : 0, 
      "CreatedDate" : "0001-01-01T00:00:00", 
      "ModifiedBy" : 0, 
      "ModifiedDate" : "0001-01-01T00:00:00", 
      "IsActive" : false, 
      "EntityStatus" : 0, 
      "ErrorMessage" : null, 
      "ExternalID" : 0, 
      "ExternalSystemID" : 0 
     }, 
     "Id" : 2, 
     "Name" : null, 
     "CreatedBy" : 0, 
     "CreatedDate" : "0001-01-01T00:00:00", 
     "ModifiedBy" : 0, 
     "ModifiedDate" : "0001-01-01T00:00:00", 
     "IsActive" : false, 
     "EntityStatus" : 0, 
     "ErrorMessage" : null, 
     "ExternalID" : 0, 
     "ExternalSystemID" : 0 
    } 
] 

здесь мои "chosenCountries" будет JobOrderDelivTranscript(). если я выбираю первый вариант, он должен быть сопоставлен с JobOrderDelivTranscript() [0] .TranscriptType.Id. в их примере они используют строковый массив, но мне приходится связываться со сложными данными. Как мне это сделать.

Даже я попытался с помощью пользовательских привязок

ko.bindingHandlers['selectedCustomOptions'] = { 
      getSelectedValuesFromSelectNode: function (selectNode) { 
       var result = []; 
       var nodes = selectNode.childNodes; 
       for (var i = 0, j = nodes.length; i < j; i++) { 
        var node = nodes[i], tagName = ko.utils.tagNameLower(node); 
        if (tagName == "option" && node.selected) 
         result.push(ko.selectExtensions.readValue(node)); 
        else if (tagName == "optgroup") { 
         var selectedValuesFromOptGroup = ko.bindingHandlers['selectedCustomOptions'].getSelectedValuesFromSelectNode(node); 
         Array.prototype.splice.apply(result, [result.length, 0].concat(selectedValuesFromOptGroup)); // Add new entries to existing 'result' instance 
        } 
       } 
       return result; 
      }, 
      'init': function (element, valueAccessor, allBindingsAccessor) { 
       ko.utils.registerEventHandler(element, "change", function() { 
        var value = valueAccessor(); 
        var valueToWrite = ko.bindingHandlers['selectedCustomOptions'].getSelectedValuesFromSelectNode(this); 
        ko.jsonExpressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite); 
       }); 
      }, 
      'update': function (element, valueAccessor) { 
       if (ko.utils.tagNameLower(element) != "select") 
        throw new Error("values binding applies only to SELECT elements"); 

       var newValue = ko.utils.unwrapObservable(valueAccessor()); 
       if (newValue && typeof newValue.length == "number") { 
        var nodes = element.childNodes; 
        for (var i = 0, j = nodes.length; i < j; i++) { 
         var node = nodes[i]; 
         if (ko.utils.tagNameLower(node) === "option") 
          ko.utils.setOptionNodeSelectionState(node, arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0); 
        } 
       } 
      } 
     }; 

     function arrayIndexOf (array, item) { 
      if (typeof Array.prototype.indexOf == "function") 
       return Array.prototype.indexOf.call(array, item); 
      for (var i = 0, j = array.length; i < j; i++) 
       if (array[i].TranscriptType.Id() === item.Id) 
        return i; 
      return -1; 
     } 

Я сделал варианты получить выбранный, но JSON данные не получали обновленные.

есть ли какой-либо простой способ?

Заранее спасибо.

ответ

1

Я не 100% Я понимаю ваш вопрос, но, похоже, вы пытаетесь связать сложный объект с привязкой selectedOptions. Есть два способа сделать то, что вы хотите. Во-первых, используйте привязку optionsValue в сочетании с вычисленным, чтобы вытащить свой идентификатор привязки до уровня корня объекта (к сожалению, привязка optionsValue работает только в корневом каталоге, поэтому optionsValue: 'TranscriptType.Id' не работает).

<p>Choose some countries you'd like to visit:</p> 
<select data-bind="options: availableCountries, optionsText: optionsText, 
     optionsValue: 'id', selectedOptions: 
     chosenCountries" size="5" multiple="true"></select> 

<p data-bind="text: ko.toJSON(chosenCountries)"> 
</p> 

var JobOrderDelivTranscript = function(id) { 
    var self = this; 
    this.TranscriptType = { 
     Id : id 
    } 
    this.id = ko.computed(function() { 
     return self.TranscriptType.Id 
    }); 
}; 

http://jsfiddle.net/madcapnmckay/6K6kH/

Второй способ не использовать optionsValue, в этом случае KO будет использовать ссылки на объект для проверки равенства. До тех пор, пока вы сохраняете одни и те же ссылки на объекты в своем выбранном массиве «Кассы», все будет работать.

var viewModel = function() { 
    var self = this; 
    this.availableCountries = ko.observableArray([ 
     new JobOrderDelivTranscript("Some Transcript 1"), 
     new JobOrderDelivTranscript("Some Transcript 2"), 
     new JobOrderDelivTranscript("Some Transcript 3")]); 

    this.chosenCountries = ko.observableArray([ self.availableCountries()[0] ]); 

    this.optionsText = function(option) { 
     return option.TranscriptType.Id; 
    };   
}; 

var vm = new viewModel(); 
vm.chosenCountries.push(vm.availableCountries()[1]); 

http://jsfiddle.net/madcapnmckay/hmsqf/

Оба способа имеют свои преимущества и недостатки, это зависит от конкретной ситуации, что является правильным нужным.

EDIT

Чтобы сделать то же самое с отображением плагина вам нужно будет использовать Параметры отображения, которые охватываются в документации here under "Advanced Usage".

Вот пример, который вы должны уметь адаптировать.

http://jsfiddle.net/madcapnmckay/hmsqf/2/

Для того, чтобы структурировать ваш код лучше, я бы рекомендовал создать много JavaScript классов, как я в примере с приказом это позволяет логика, которая должна содержаться в дискретных блоков. Я бы также не рекомендовал использовать старые селектора jquery, многие новички с KO думают, что все в порядке, чтобы смешать их. По-моему, это разбавляет разделение проблем между вашей моделью взгляда и точкой зрения.Зачем использовать $(selector).click, когда вы можете использовать привязку click.

Надеюсь, это поможет.

+0

Спасибо за ваш быстрый ответ. Пожалуйста, найдите мое примерное приложение в jsfiddle [link] http://jsfiddle.net/nanda/uVjUv/1/. Я использую картографическую модель. У меня есть несколько рабочих мест, и каждый заказ будет иметь список. Мне нужно привязать окно списка. Еще раз спасибо – Nanda

+0

@ Nanda - Помог ли мой ответ вам вообще? Я не могу понять, что происходит в вашем jsfiddle, можете ли вы упростить его. Я бы сказал, что если вы хотите сделать то, что я показал с помощью плагина сопоставления, вы, вероятно, должны использовать некоторые методы отображения, чтобы правильно формировать ваши данные. – madcapnmckay

+0

действительно ваш ответ помог мне. Я получил большую ясность в отношении перекрестного привязки нокаута. Если я использую ручной режим просмотра, я могу следить за вашим кодом. Но я использую картографический плагин, и я новичок для нокаута и картографирования. Поэтому я не могу использовать расширенные параметры. Но я попробую. Любая идея о картографии, пожалуйста, поделитесь своими мыслями. Большое вам спасибо madcapnmckay. – Nanda

Смежные вопросы