knockout.js
2013-02-18 9 views 10 likes 
10

私は動的に列ヘッダーを使用してテーブルをソートする方法JS &必要ヘルプワークアウトをノックアウトする新たなんです。ノックアウトJS - 表に列ヘッダーを使用してソートするには、

以下は、私のコードの一部です:

HTML:私の見解モデルで

<table> 


<thead> 
       <tr data-bind="click: sortFunction"> 
        <th id='id'>Id</th> 
        <th id='name'>Name</th> 
        <th id='description'>Description</th> 
       </tr> 
      </thead> 

       <tbody data-bind="foreach: deptList"> 
        <tr> 
          <td><span data-bind="text: id" /></td> 
          <td><span data-bind="text: name" /></td> 
          <td><span data-bind="text: description" /></td> 
        </tr>  
       </tbody> 
      </table> 

私はテーブルのヘッダーを使用してデータテーブルをソートするために使用する次の関数をしました。

のViewModel:

self.deptList = ko.observableArray(mylist); 
self.sortColumn = ko.observable("id"); 
self.isSortAsc = ko.observable("True"); 

var Dept = function (id, name, description) { 
      this.id = ko.observable(id); 
      this.name = ko.observable(name); 
      this.description = ko.observable(description); 
      }; 

var mylist = [ 
      new Dept(1, "Dept 1", "D1"), 
      new Dept(2, "Dept 2", "D6"), 
      new Dept(3, "Dept 3", "D3"), 
      new Dept(4, "Dept 4", "D4")]; 


self.sortFunction = function (data, event) { 

       if(self.sortColum === event.target.id) 
        self.isSortAsc = !self.isSortAsc; 
       else 
       { 
        self.sortColumn = event.target.id; 
        self.isSortAsc = "True"; 
       }    


       self.deptList.sort(function (a, b) { 
         if(self.sortColum === 'id') 
         { 
          if(self.isSortAsc) 
           a.id < b.id ? -1 : 1; 
          else 
           a.name < b.name ? 1 : -1; 
         } 
         else if(self.sortColum === 'name'){ 
          if(self.isSortAsc) 
           a.name < b.name ? -1 : 1; 
          else 
           a.name < b.name ? 1 : -1; 
         } 
         else (self.sortColum === 'description'){ 
          if(self.isSortAsc) 
           a.description < b.description ? -1 : 1; 
          else 
           a.description < b.description ? 1 : -1; 
         } 

       }); 

      }; 

がある場合、上記のコードは、私がこれを行うには良い方法があるはずだと思う働いているにもかかわらず(私は、パラメータとしてカラムIDを渡すことを意味する)に有用であろう大規模な列。

私は試しました: left [self.sortColumn] < right [self.sortColumn]? -1:期待通りに機能しなかった1 。

それは動的な列名を経由して並べ替えることが可能である場合は、サンプルコードを示してください。 ありがとうございます。 self.sortColumnは、あなたが機能としてそれを呼び出すことで値を取得する必要がどのko.observableあるので

答えて

2
left[self.sortColumn] < right[self.sortColumn] ? -1 : 1 

は動作しません。

self.deptList.sort(function (a, b) { 
    if(self.isSortAsc()) 
    a[self.sortColumn()]() < b[self.sortColumn()]() ? -1 : 1; 
    else 
    a[self.sortColumn()]() < b[self.sortColumn()]() ? 1 : -1; 
}); 

は、とも私はここ

<table class="dept_table"> 
    <thead> 
     <tr data-bind="click: sortFunction"> 
      <th id='id'>Id</th> 
      <th id='name'>Name</th> 
      <th id='description'>Description</th> 
     </tr> 
    </thead> 

    <tbody data-bind="foreach: deptList"> 
     <tr> 
       <td><span data-bind="text: id" /></td> 
       <td><span data-bind="text: name" /></td> 
       <td><span data-bind="text: description" /></td> 
     </tr>  
    </tbody> 
</table> 
<script> 
// deptlist data 
var mylist = [ 
      {id:1, name:"Dept 1", description: "D1"}, 
      {id:2, name:"Dept 2", description: "D6"}, 
      {id:3, name:"Dept 3", description: "D3"}, 
      {id:4, name:"Dept 4", description: "D4"}]; 

// Deptlist-item Viewmodel 
var Dept = function (data) { 
    var self = this; 

    for(var key in data){ 
    // this is the lazy approach usually you should only use observables where they are needed 
    if(data.hasOwnProperty(key))this[key] = ko.observable(data[key]); 
    } 
}; 

// Deptlist Viewmodel 
var Deptlist = function(table_data){ 
    var self = this; 

    this.deptList = ko.observableArray([]); 
    this.sortColumn = ko.observable("id"); 
    this.isSortAsc = ko.observable(true); 

    for(var i = 0;i < table_data.length;i++){ 
    if(table_data.hasOwnProperty(i))this.deptList.push(new Dept(table_data[i])); 
    } 

    this.sortFunction = function(){ 
    if(self.sortColumn() === event.target.id) 
     self.isSortAsc(!self.isSortAsc()); 
    else 
    { 
     self.sortColumn(event.target.id); 
     self.isSortAsc(true); 
    } 

    self.deptList.sort(function (a, b) { 
      if(a[self.sortColumn()]() < b[self.sortColumn()]())return !self.isSortAsc(); 
      else return self.isSortAsc(); 
    }); 
    } 
}; 

var deptList = new Deptlist(mylist); 

ko.applyBindings(deptList,$('.dept_table')[0]); 

</script> 
+0

"true"と "false"の代わりに真のブール値を使用してください。空の文字列はtrueに評価されます – cioddi

+0

あなたの指示とサンプルコードをありがとう。 Iは、関数パラメータとして(データ、イベント)を指定した場合、上記サンプルは、作業を行います。 (this.sortFunction = function(data、event){)。しかし、私が最初にId列そのものをクリックすると、降順でのIDを並べ替えることになっています。しかし、不思議なことに値3,1,2,4を与えます。(Idの降順で)代わりに4,3,2,1が必要です。これをもう一度確認してください。再度、感謝します。 – Uwaisul

+0

比較機能であなたが のような値にアクセスすることを確認して[self.sortColumn()]() cioddi

33

は実施例に一緒に入れている

if(self.sortColum === event.target.id) 
        self.isSortAsc(!self.isSortAsc()); 
       else 
       { 
        self.sortColumn(event.target.id); 
        self.isSortAsc("True"); 
       } 

代わりの

if(self.sortColum === event.target.id) 
        self.isSortAsc = !self.isSortAsc; 
       else 
       { 
        self.sortColumn = event.target.id; 
        self.isSortAsc = "True"; 
       } 

のような観測に値を設定する必要がありますあなたに追加することができるクイックバインディングハンドラウルティス。バインディングで定義されたように目のプロパティ名に従って列をソートしますクリックすると。

ko.bindingHandlers.sort = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var asc = false; 
     element.style.cursor = 'pointer'; 

     element.onclick = function(){ 
      var value = valueAccessor(); 
      var prop = value.prop; 
      var data = value.arr; 

      asc = !asc; 

      data.sort(function(left, right){ 
       var rec1 = left; 
       var rec2 = right; 

       if(!asc) { 
        rec1 = right; 
        rec2 = left; 
       } 

       var props = prop.split('.'); 
       for(var i in props){ 
        var propName = props[i]; 
        var parenIndex = propName.indexOf('()'); 
        if(parenIndex > 0){ 
         propName = propName.substring(0, parenIndex); 
         rec1 = rec1[propName](); 
         rec2 = rec2[propName](); 
        } else { 
         rec1 = rec1[propName]; 
         rec2 = rec2[propName]; 
        } 
       } 

       return rec1 == rec2 ? 0 : rec1 < rec2 ? -1 : 1; 
      }); 
     }; 
    } 
    }; 

これは、列ごとに別々の関数を作成する必要がないという点でもう少し洗練されています。より完全な実例はここにあります:http://jsfiddle.net/brendonparker/6S85t/

+4

私のプロパティが観測可能だったので、私はko.unwrapでleft [prop]とright [prop]にコールをラップする必要がありました。 – Betty

+0

更新されたスニペットとフィドルをご覧ください。私は、それ自身観測可能なプロパティの並べ替えを処理するために少し強化しました。 – brendonparker

+0

brendonparkerのコードを使用する場合は、プロパティがノックアウト観測値であれば、data-bind = "sort:{arr:array、prop:field()}"のようにバインディングを指定する必要があります。フィールド名の後ろの()に注意してください。それ以外の場合は、アクセサ関数のメモリアドレスをソートします。 –

 関連する問題

  • 関連する問題はありません^_^