2012-05-08 10 views
8

Ho un Ember.ArrayController con contenuto non ordinato.Ordina contenuto di ArrayController

Voglio sapere se è possibile ordinare il contenuto di un ArrayController senza utilizzare una nuova proprietà.

potrei naturalmente creare una nuova proprietà:

App.MyArrayController = Em.ArrayController.extend({ 
    mySortMethod: function(obj1, obj2) { 
    // some code here 
    }, 
    updateSortedContent: function() { 
    var content = this.get('content'); 
    if (content) { 
     var sortedContent = content.copy(); 
     sortedContent.sort(this.mySortMethod); 
     this.set('sortedContent', sortedContent); 
    } 
    }.observes('content') 
}); 

Ma spero che ci sia un modo migliore che non duplica il contenuto.

+0

possibile duplicato del [Sort array di oggetti EmberJS dalla proprietà] (http://stackoverflow.com/questions/9041505/sort-array-of-emberjs-objects-by-property) –

risposta

35

UPDATE

L'ultima versione di Ember ha effettivamente l'ordinamento integrato. ArrayController ora include lo Ember.SortableMixin che si attiverà se si specifica sortProperties (matrice) e facoltativamente sortAscending (booleano).

Nota: con il nuovo SortableMixin, è ancora necessario fare riferimento a arrangedContent per ottenere la versione ordinata. Il modello stesso rimarrà intatto. (Grazie a Jonathan Tran)

App.userController = Ember.ArrayController.create({ 
    content: [], 
    sortProperties: ['age'], 
    sortAscending: false 
}) 

ORIGINALE RISPOSTA

Il modo corretto per farlo è quello di utilizzare la proprietà arrangedContent di ArrayProxy. Questa proprietà è progettata per essere sovrascritta per fornire una versione ordinata o filtrata dell'array di contenuto.

App.userController = Ember.ArrayController.create({ 
    content: [], 
    sort: "desc", 
    arrangedContent: Ember.computed("content", function() { 
    var content, sortedContent; 
    content = this.get("content"); 
    if (content) { 
     if (this.get("sort") === "desc") { 
     this.set("sort", "asc"); 
     sortedContent = content.sort(function(a, b) { 
      return a.get("age") - b.get("age"); 
     }); 
     } else { 
     this.set("sort", "desc"); 
     sortedContent = content.sort(function(a, b) { 
      return b.get("age") - a.get("age"); 
     }); 
     } 
     return sortedContent; 
    } else { 
     return null; 
    } 
    }).cacheable() 
}); 
+0

Definire un ordinamentoLa specie ordina per impostazione predefinita. Può essere modificato per adattare l'ordinamento solo quando viene registrata una richiesta utente (tramite un menu a discesa o qualcosa del genere)? – Rajat

+0

Si definiscono le proprietà di ordinamento di default e crescente per essere qualsiasi cosa sia "normale" per il contenuto. Quindi fai una piccola azione che cambia queste due proprietà tramite pulsanti o elenchi a discesa e la magia accade. Ho un metodo reSort sul controller che imposta la proprietà sort (ne utilizzo solo una) su ciò che il pulsante invia come argomento. E se la proprietà è uguale a quella già impostata, la interpreta come un'indicazione per invertire l'ordine in ordine decrescente. https://gist.github.com/3744939 –

+8

Nota: con la nuova SortableMixin, è ancora necessario fare riferimento a 'arrangedContent' per ottenere la versione ordinata. Questo mi ha fatto inciampare all'inizio. –

2

È necessario ordinare manualmente gli array, incluso il contenuto di qualsiasi controller dell'array, in Ember. È sempre possibile sostituire content con la matrice ordinata invece di mantenere entrambi gli array.

Aggiornamento

Ecco un esempio di quello che penso che stai cercando: http://jsfiddle.net/ud3323/yjs8D/

Aggiornamento # 2

Aggiornato questo esempio per utilizzare le nuove modifiche vista di contesto. https://gist.github.com/2494968

Manubrio

<script type="text/x-handlebars" > 
Will Display and Sort by Age (after 2 sec)<br/><br/> 

{{#each App.userController}} 
    {{#view App.RecordView}} 
     {{name}} - {{age}} 
    {{/view}} 
{{/each}} 
</script> 

JavaScript

App = Ember.Application.create({ 
    ready: function() { 
     Ember.run.later(this, function() { 
      Ember.run.later(this, function() { 
       App.get('userController').set('content', [ 
        Ember.Object.create({ name:"Jeff", age:24 }), 
        Ember.Object.create({ name:"Sue", age:32 }), 
        Ember.Object.create({ name:"Jim", age:12 }) 
       ]); 
     }, 2000); 
     Ember.run.later(this, function() { 
      // Make the controller's content sort again in reverse this time 
      App.userController.notifyPropertyChange('content'); 
     }, 4000); 
    } 
}); 

App.userController = Ember.ArrayController.create({ 
    content: [], 

    contentDidChange: Ember.observer(function(userCtr, prop) { 
     if(!Ember.empty(this.get('content'))) { 
      console.log('about to begin sort'); 
      this.sortContent(); 
     } 

     this._super(); 
    }, 'content'), 

    sort:"desc", 

    sortContent:function() { 
     var content = this.get("content"), sortedContent; 

     if (this.get("sort") == "desc") { 
      this.set("sort", "asc"); 
      sortedContent = content.sort(function(a,b){ 
       return a.get("age") - b.get("age"); 
      }); 
     } else { 
      this.set("sort","desc"); 
      sortedContent = content.sort(function(a,b){ 
       return b.get("age") - a.get("age"); 
      }); 
     } 

     this.set("content",sortedContent); 
    } 
}); 

App.RecordView = Ember.View.extend({}); 

+0

sì, ma io non so dove sostituirlo, perché se l'osservatore 'contenuto' sostituisce il contenuto, la richiamata verrà inviata di nuovo, e ancora e ancora, ... – louiscoquio

+0

Vedere il mio aggiornamento. Risolve quel problema. –

+0

funziona! L'ho già provato, ma ho chiamato 'this._super()' prima di ordinare il contenuto in modo che non funzionasse. Ad ogni modo, grazie – louiscoquio