簡體   English   中英

綁定多個下拉列表中的擊倒.js

[英]binding multi dropdown list in knockout.js

我有多個下拉列表,需要執行以下操作:
1.確保在一個下拉列表中選擇值時,它不會出現在其他列表中(此處找不到合適的解決方案)。
2.選擇值“文本”時,將出現一個文本字段( <input> ),而不是“是/否”下拉列表。
3.“選擇選項”將僅出現在第一行(仍在起作用)。
4.確保如果選擇“文本”,它將始終位於頂部(仍在工作)。

的jsfiddle

HTML

  <div class='liveExample'> 
   <table width='100%'>
                <tbody data-bind='foreach: lines'>
                    <tr>
                        <td>
                            Choose option:
                        </td>
                        <td>
                            <select data-bind='options: filters, optionsText: "name", value: filterValue'> </select>
                        </td>
                        <td data-bind="with: filterValue">
                            <select data-bind='options: filterValues, optionsText: "name", value: "name"'> </select>
                        </td>
                        <td>
                            <button href='#' data-bind='click: $parent.removeFilter'>Remove</button>
                        </td>
                    </tr>
                </tbody>
            </table>
            <button data-bind='click: addFilter'>Add Choice</button>

JAVASCRIPT

var CartLine = function() {
    var self = this;
    self.filter = ko.observable();
    self.filterValue = ko.observable();

    // Whenever the filter changes, reset the value selection
    self.filter.subscribe(function() {
        self.filterValue(undefined);
    });
};

var Cart = function() {
    // Stores an array of filters
    var self = this;
    self.lines = ko.observableArray([new CartLine()]); // Put one line in by default

    // Operations
    self.addFilter = function() { self.lines.push(new CartLine()) };
    self.removeFilter = function(line) { self.lines.remove(line) };
};


ko.applyBindings(new Cart());

我會在這里感謝您的協助! 主要針對第一個問題。

謝謝!
麥克風

如果要基於UI中已選擇的選項來限制選項,則需要確保每個cartLine都有自己的過濾器數組。 讓我們像這樣在構造函數中傳遞它:

var CartLine = function(availableFilters) {
  var self = this;
  self.availableFilters = availableFilters;

  // Other code
  // ...
};

您必須使用此新的viewmodel屬性,而不是全局filters數組:

<td>
  <select data-bind='options: availableFilters, 
    optionsText: "name", 
    value: filterValue'> </select>
</td>

現在,我們必須找出在創建新的cartLine實例時哪些過濾器仍然可用。 Cart管理所有lines ,並具有addFilter功能。

self.addFilter = function() {
  var availableFilters = filters.filter(function(filter) {
    return !self.lines().some(function(cartLine) {
      var currentFilterValue = cartLine.filterValue();
      return currentFilterValue &&
        currentFilterValue.name === filter.name;
    });
  });

  self.lines.push(new CartLine(availableFilters))
};

新的CartLine實例僅獲取尚未在其他任何行中使用的過濾器。 (注意:如果要在較舊的瀏覽器中使用Array.prototype.some ,則可能需要使用polyfill

剩下的唯一的事情就是用戶體驗決定,而不是“編碼決定”:您是否希望用戶在添加新決定后能夠更改以前的“選擇”? 如果是這種情況,則需要創建計算的availableFilters數組,而不是普通的數組。

這是一個包含我上面發布的代碼的分叉小提琴: http : //jsfiddle.net/ztwcqL69/請注意,您可以創建雙選,因為在添加新選項之后,選項仍可編輯。 如果您評論期望的行為,我可以幫助您找到解決方法。 這可能需要進行一些大的更改...我提供的解決方案更多是朝着正確方向的指針。

編輯:我為沒有提供最終解決方案感到難過,所以這是另一種方法:

如果要追溯更新availableFilters ,可以這樣進行:

CartLine引用其siblings (其他購物ko.computed通過使用siblings及其filterValueko.computed創建對任何更改的filterValue

var CartLine = function(siblings) {
  var self = this;

  self.availableFilters = ko.computed(function() {
    return filters.filter(function(filter) {
      return !siblings()
        .filter(function(cartLine) { return cartLine !== self })
        .some(function(cartLine) {
        var currentFilterValue = cartLine.filterValue();
        return currentFilterValue &&
          currentFilterValue.name === filter.name;
      });
    });
  });

  // Other code...
};

像這樣創建新的購物self.lines.push(new CartLine(self.lines))self.lines.push(new CartLine(self.lines)) 從一個空數組開始,然后使用addFilter推入第一個CartLine

關於點2:您可以創建一個基於filterValue排序的可計算觀察值:

self.sortedLines = ko.computed(function() {

  return self.lines().sort(function(lineA, lineB) {
    if (lineA.filterValue() && lineA.filterValue().name === "Text") return -1;
    if (lineB.filterValue() && lineB.filterValue().name === "Text") return 1;

    return 0;
  });

});

第3點 :將其移至foreach之外。

第4點 :使用if綁定:

<td data-bind="with: filterValue">
  <!-- ko if: name === "Text" -->
  <input type="text">
  <!-- /ko -->
  <!-- ko ifnot: name === "Text" -->
  <select data-bind='options: filterValues, optionsText: "name", value: "name"'> </select>          
   <!-- /ko -->
<td>

更新的小提琴包含以下代碼: http : //jsfiddle.net/z22m1798/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM