2012-05-08 16 views
8

Ich habe eine Ember.ArrayController, die einen unsortierten Inhalt hat.Inhalt von ArrayController sortieren

Ich möchte wissen, ob es möglich ist, den Inhalt eines ArrayController zu sortieren, ohne eine neue Eigenschaft zu verwenden.

Ich könnte natürlich eine neue Eigenschaft erstellen:

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

Aber ich hoffe, dass es einen besseren Weg, die den Inhalt nicht dupliziert.

+0

möglich Duplikat von [Sortieren Array von EmberJS Objekten von Eigentum] (http://stackoverflow.com/questions/9041505/sort-array-of-emberjs-objects-by-property) –

Antwort

35

UPDATE

Die neueste Version von Ember hat tatsächlich eine eingebaute Sortierfunktion. ArrayController enthält jetzt die Ember.SortableMixin, die aktiviert wird, wenn Sie sortProperties (Array) und optional sortAscending (Boolean) angeben.

Hinweis: Mit der neuen SortableMixin müssen Sie immer noch auf arrangedContent verweisen, um die sortierte Version zu erhalten. Das Modell selbst bleibt unberührt. (Danke an Jonathan Tran)

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

ORIGINAL ANTWORT

Der richtige Weg, dies zu tun, ist die arrangedContent Eigenschaft ArrayProxy zu verwenden. Diese Eigenschaft wurde so entworfen, dass sie außer Kraft gesetzt wird, um eine sortierte oder gefilterte Version des Inhaltsarrays bereitzustellen.

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

Das Sortieren einer sortProperty wird standardmäßig sortiert. Kann dies geändert werden, um die Sortierung nur dann anzupassen, wenn eine Benutzeranforderung registriert ist (über ein Dropdown oder etwas)? – Rajat

+0

Sie definieren die Standardsortiereigenschaften und aufsteigend, was auch immer "normal" für Ihren Inhalt ist. Dann machst du eine kleine Aktion, die diese beiden Eigenschaften über Buttons oder Drop-Downs verändert und Magie passiert. Ich habe eine reSort-Methode auf dem Controller, die die Sortiereigenschaft (ich verwende nur eine) zu dem, was die Schaltfläche als ein Argument sendet. Und wenn die Eigenschaft die gleiche wie die bereits gesetzte Eigenschaft ist, interpretiert sie dies als eine Indikation, um die absteigende Reihenfolge umzukehren. https://gist.github.com/3744939 –

+8

Hinweis: Mit der neuen SortableMixin müssen Sie noch auf "arrangedContent" verweisen, um die sortierte Version zu erhalten. Das hat mich zuerst gestolpert. –

2

Sie müssen Arrays in Ember manuell sortieren, einschließlich des Inhalts des Array-Controllers. Sie könnten content immer durch Ihr sortiertes Array ersetzen, anstatt beide Arrays zu behalten.

aktualisieren

Hier ist ein Beispiel dafür, was ich denke, Sie suchen: http://jsfiddle.net/ud3323/yjs8D/

Update # 2

diesem Beispiel aktualisiert die neue Ansicht Kontextänderungen zu verwenden. https://gist.github.com/2494968

Lenker

<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

yep, aber ich Ich weiß nicht, wo ich es ersetzen soll, denn wenn der Inhaltsbeobachter den Inhalt ersetzt, wird der Rückruf erneut gesendet und wieder und wieder ... – louiscoquio

+0

Siehe mein Update. Es löst dieses Problem. –

+0

es funktioniert! Ich habe das schon ausprobiert, aber ich habe 'this._super()' vor dem Sortieren des Inhalts aufgerufen, so dass es nicht funktioniert hat. Wie auch immer, danke – louiscoquio

Verwandte Themen