2013-02-18 24 views
10

Sono nuovo di knockout js & bisogno di aiuto allenamento come ordinare dinamicamente una tabella utilizzando l'intestazione della colonna.knockout js - Ordinamento tabella utilizzando le intestazioni di colonna

seguito fa parte del mio codice:

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> 

Nel mio modello vista ho la seguente funzione, che io uso per ordinare una tabella di dati utilizzando l'intestazione della tabella.

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

       }); 

      }; 

Sebbene sopra codice funzioni Credo ci dovrebbe essere un modo migliore per fare questo (intendo passando l'id colonna come parametro) che sarà utile quando c'è un grande numero di colonne.

Ho provato: lasciato [self.sortColumn] < right [self.sortColumn]? -1: 1 che non ha funzionato come previsto.

Se è possibile ordinare tramite un nome di colonna dinamico, mostrare un codice di esempio. Grazie in anticipo.

risposta

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

non funziona perché è un self.sortColumn ko.observable su cui si deve ottenere il valore chiamando come una funzione.

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

e inoltre è necessario impostare i valori su osservabili come

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

invece di

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

ho messo insieme un esempio di lavoro

<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

e utilizzare valori booleani reali anziché "true" e "false" come stringhe non vuote restituiscono true – cioddi

+0

Grazie mille per le istruzioni e il codice di esempio. L'esempio sopra riportato funziona quando si specifica (dati, evento) come parametri di funzione. (this.sortFunction = function (data, event) {). Ma si suppone di ordinare gli ID in ordine decrescente se inizialmente clicco sulla colonna Id. Ma stranamente dà valori 3, 1, 2, 4. Ho invece bisogno di 4,3,2,1 (per ordine decrescente di Id). Potresti ricontrollare su questo? Grazie ancora. – Uwaisul

+0

fare in modo che nella funzione di confronto si accede valori come un [self.sortColumn()]() cioddi

33

Ecco un bindingHandler veloce che puoi aggiungere a te è così. Facendo clic su th ordinerà la colonna in base al nome della proprietà come definito nell'associazione.

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

Questo è un po 'più elegante in quanto non è necessario creare una funzione separata per ogni colonna. Un esempio di funzionamento più completo può essere trovato qui: http://jsfiddle.net/brendonparker/6S85t/

+4

perché le mie proprietà erano osservabili avevo bisogno di avvolgere le chiamate a sinistra [prop] e destra [prop] con ko.unwrap. – Betty

+0

Vedere lo snippet e il violino aggiornati. L'ho migliorato un po 'per gestire l'ordinamento su proprietà che sono esse stesse osservabili. – brendonparker

+0

Per coloro che cercano di utilizzare il codice di brendonparker, se la proprietà è osservabile a eliminazione diretta, è necessario specificare l'associazione in questo modo: data-bind = "sort: {arr: array, prop: field()}". Nota il() dopo il nome del campo. Altrimenti sarà l'ordinamento sull'indirizzo di memoria della funzione di accesso. –

Problemi correlati