2013-02-18 22 views
10

Jestem nowy w nokaucie js & potrzebujesz pomocy w treningu, jak dynamicznie sortować tabelę za pomocą nagłówka kolumny.nokaut js - sortowanie tabel przy użyciu nagłówków kolumn

obserwuję jest częścią mojego kodu:

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> 

moim zdaniem modelu mam następującą funkcję którego używam do sortowania tabeli danych przy użyciu nagłówka tabeli.

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; 
         } 

       }); 

      }; 

Chociaż powyższy kod działa myślę, że nie powinno być lepszym sposobem, aby to zrobić (mam na myśli przekazując identyfikator kolumny jako parametr), która będzie przydatna, gdy istnieje duża liczba kolumn.

Próbowałem: left [self.sortColumn] < right [self.sortColumn]? -1: 1 , który nie działał zgodnie z oczekiwaniami.

Jeśli istnieje możliwość sortowania za pomocą dynamicznej nazwy kolumny, proszę wyświetlić przykładowy kod. Z góry dzięki.

Odpowiedz

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

nie działa, ponieważ self.sortColumn jest ko.observable na które trzeba uzyskać wartość nazywając go jako funkcja.

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; 
}); 

i również trzeba ustawić wartości na obserwabli jak

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

zamiast

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

mam połączyć przykład roboczych

<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

i używać prawdziwych wartości boolowskich zamiast "prawda" i "fałsz", ponieważ niepuste ciągi oceniają jako prawdziwe – cioddi

+0

Wielkie dzięki za instrukcje i przykładowy kod. Powyższy przykład działa, gdy określam (dane, zdarzenie) jako parametry funkcji. (this.sortFunction = funkcja (dane, zdarzenie) {). Ale powinien sortować identyfikatory w porządku malejącym, jeśli najpierw kliknę kolumnę Id. Ale dziwnie daje wartości 3, 1, 2, 4. Potrzebuję 4,3,2,1 zamiast (dla malejącej kolejności identyfikatorów). Czy możesz to sprawdzić? Dzięki jeszcze raz. – Uwaisul

+0

upewnić się, że w funkcji porównania dostęp wartości jak A [self.sortColumn()]() cioddi

33

Oto quick bindingHandler, który możesz dodać do yo ur th's. Po kliknięciu th posortuje kolumnę zgodnie z nazwą właściwości zdefiniowaną w powiązaniu.

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; 
      }); 
     }; 
    } 
    }; 

Jest to trochę bardziej eleganckie, ponieważ nie trzeba tworzyć oddzielnej funkcji dla każdej kolumny. Pełniejszy przykład działania można znaleźć tutaj: http://jsfiddle.net/brendonparker/6S85t/

+4

ponieważ moje właściwości były obserwowalne, musiałem zawijać wywołania na lewo [prop] i right [prop] za pomocą ko.unwrap. – Betty

+0

Zobacz zaktualizowany fragment i skrzypce. Ulepszyłem to nieco, aby obsłużyć sortowanie na właściwościach, które same są obserwowalne. – brendonparker

+0

Dla tych, którzy chcą użyć kodu brendonparker, jeśli twoja własność jest nokautowalna, będziesz musiał określić swoje powiązanie w ten sposób: data-bind = "sort: {arr: array, prop: field()}". Zwróć uwagę() po nazwie pola. W przeciwnym razie będzie sortowanie na adres pamięci funkcji dostępowej. –

Powiązane problemy