2014-10-30 4 views
0

У меня есть массив текстов, которые я показываю в <select>.Проблема фильтрации массива с нокаутом и селекторами

Тексты могут иметь другую версию, и я хочу отфильтровать <select> на основе самой последней версии.

Я думаю, что есть более элегантные способы сделать это (предложения приветствуются), но я решил использовать 2 <select> s для альтернативной видимости в зависимости от флажка.

Код взлома, но результат выглядит довольно неплохо. К сожалению, есть ошибка.

У меня есть два наблюдаемых с указанием выбранной опции в соответствующих массивах:

self.SelectedText = ko.observable(); 
self.SelectedUnique = ko.observable(); 

Оба имеют подписки, но я не могу связать их вместе и в подписке, поэтому я выбрал один, чтобы быть indipendant на другом, как это:

self.SelectedUnique.subscribe(function (text) { 
    if (text) { 
     self.SelectedText(text); 
    } 
}); 

Однако выход из синхронизации.

Сценарий 1: выберите текст 1,2,3. [OK] Сценарий 2: выберите текст 2; «Только для последних версий»

Это не вызывает никаких параметров («Выбрать ...»). Не то, что я хочу.

Все ухудшается.

Сценарий 3: снять отметку; выберите текст 3; Затем снова проверьте «Последние версии».

Теперь выбранный вариант выбора установлен для выбора варианта № 2 нефильтрованного.

Возможно, существует простая проблема. Я просто не могу заставить его работать. Вот скрипка: Fiddle: http://jsfiddle.net/h5mt51gv/6/

Вся помощь и предложения оценены!

+0

Вы знакомы с перезаписываемых вычислен наблюдаемыми? – Keen

+0

Вы говорите, что делаете * не * хотите ... но вы не говорите, что хотите. ;) Что следует выбирать, если опция недоступна? – Tomalak

+0

Хорошая точка Томалак. когда опция недоступна, я думаю, что опция «Выбрать ..» актуальна. В качестве альтернативы можно выбрать последнюю версию (вместе с информативным всплывающим окном). Я не уверен в этом, но рассмотрю эту проблему позже. –

ответ

1

Я упростил свой подход:

  • <select> связывается с вычисленным списком опций (visibleTextBatches)
  • этот вычисленный список зависит от состояния флажка (latestOnly), эффективно переключаясь между полным и отфильтрованный список
  • еще один расчетный список (latestTextBatches), который содержит последнюю версию для каждой группы
  • магазины <select> фактический выбранный TextBatch объект в наблюдаемом (selectedTextBatch)
  • есть подписка на visibleTextBatches, что приводит к тому, что последний выбирается TextBatch, чтобы стать текущим при фильтрации списка. Когда список не фильтруется, он ничего не делает.

function TextBatch(data) { 
 
    this.textbatchId = data.textbatchId; 
 
    this.parentId = data.parentId; 
 
    this.version = data.version; 
 
    this.title = ko.observable(data.title); 
 
} 
 

 
function ViewModel() { 
 
    var self = this; 
 

 
    // read up on the mapping plugin, too 
 
    self.textBatches = ko.observableArray([ 
 
     new TextBatch({textbatchId: 1, parentId: 1, version: 1, title: "TB1.1"}), 
 
     new TextBatch({textbatchId: 2, parentId: 1, version: 2, title: "TB1.2"}), 
 
     new TextBatch({textbatchId: 3, parentId: 3, version: 1, title: "TB2.1"}) 
 
    ]); 
 
    self.selectedTextBatch = ko.observable(); 
 
    self.latestOnly = ko.observable(false); 
 
    self.latestTextBatchGroups = ko.computed(function() { 
 
     var latest = {}; 
 
     ko.utils.arrayForEach(self.textBatches(), function (batch) { 
 
      if (!latest.hasOwnProperty(batch.parentId) || 
 
       batch.version > latest[batch.parentId].version 
 
      ) latest[batch.parentId] = batch; 
 
     }); 
 
     return latest; 
 
    }); 
 
    self.latestTextBatches = ko.computed(function() { 
 
     return ko.utils.arrayFilter(self.textBatches(), function (batch) { 
 
      return batch === self.latestTextBatchGroups()[batch.parentId]; 
 
     }); 
 
    }); 
 
    self.visibleTextBatches = ko.computed(function() { 
 
     return self.latestOnly() ? self.latestTextBatches() : self.textBatches(); 
 
    }); 
 
    self.visibleTextBatches.subscribe(function() { 
 
     var selectedBatch = self.selectedTextBatch(); 
 
     if (selectedBatch && self.latestOnly()) { 
 
      self.selectedTextBatch(
 
       self.latestTextBatchGroups()[selectedBatch.parentId] 
 
      ); 
 
     } 
 
    }); 
 
} 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
<div> 
 
    <select data-bind=" 
 
     options: visibleTextBatches, 
 
     optionsText: 'title', 
 
     optionsCaption: 'Select...', 
 
     value: selectedTextBatch 
 
    " /> 
 
</div> 
 

 
<div> 
 
    <input type="checkbox" id="chkLatestOnly" data-bind="checked: latestOnly" /> 
 
    <label for="chkLatestOnly">Latest only</label> 
 
</div> 
 

 
<hr /> 
 
<pre data-bind="text: ko.toJSON($root, null,2)"></pre>

+0

Nice @Tomalak Спасибо! Мне придется изменить логику в «ko.utils.arrayForEach» из последнихTextBatches-вычисленных, хотя, поскольку parentId получает его номер из созданного db textbatchId, таким образом, не будет равняться версии. –

+1

Я делал предположения на этом этапе, но я хотел получить эту идею. – Tomalak

+0

Другое: Какая разница между вашей «функцией ViewModel()» и (my) «var ViewModel = function()»? –

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