2012-05-08 14 views
8

Tengo un Ember.ArrayController que tiene un contenido sin clasificar.Clasificar contenido de ArrayController

Quiero saber si es posible ordenar el contenido de un ArrayController sin usar una nueva propiedad.

que podría crear, por supuesto, una nueva propiedad:

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

Pero espero que hay una mejor manera que no se duplica el contenido.

+0

posible duplicado de [Ordenar matriz de objetos EmberJS por la propiedad] (http://stackoverflow.com/questions/9041505/sort-array-of-emberjs-objects-by-property) –

Respuesta

35

ACTUALIZACIÓN

La última versión de Ember en realidad tiene clasificación incorporada. ArrayController ahora incluye el Ember.SortableMixin que se activará si especifica sortProperties (Array) y opcionalmente sortAscending (Boolean).

Nota: con el nuevo SortableMixin, aún necesita consultar arrangedContent para obtener la versión ordenada. El modelo en sí no se tocará. (Gracias a Jonathan Tran)

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

respuesta original

La forma correcta de hacerlo es utilizar la propiedad arrangedContent de ArrayProxy. Esta propiedad está diseñada para sobrescribirse para proporcionar una versión ordenada o filtrada de la matriz de contenido.

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

Definir un sortProperty ordena por defecto. ¿Se puede cambiar esto para adaptar la ordenación solo cuando se registra una solicitud de usuario (a través de un menú desplegable o algo así)? – Rajat

+0

Define las propiedades de clasificación predeterminadas y ascendentes para que sean lo que sea "normal" para su contenido. Luego realizas una pequeña acción que cambia esas dos propiedades a través de botones o menús desplegables y sucede la magia. Tengo un método reSort en el controlador que establece la propiedad sort (uso solo uno) para lo que el botón envía como argumento. Y si la propiedad es la misma que la que ya está configurada, interpreta eso como una indicación para invertir el orden de descenso. https://gist.github.com/3744939 –

+8

Nota: con el nuevo SortableMixin, aún necesita consultar 'arrangedContent' para obtener la versión ordenada. Esto me hizo tropezar al principio. –

2

Debe ordenar manualmente las matrices, incluido el contenido de cualquier controlador de matriz, en Ember. Siempre puede reemplazar content con su matriz ordenada en lugar de mantener ambas matrices.

actualización

Aquí es un ejemplo de lo que creo que está buscando: http://jsfiddle.net/ud3323/yjs8D/

Actualización # 2

Actualizado este ejemplo para utilizar los nuevos cambios de contexto vista. https://gist.github.com/2494968

Manillar

<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í, pero no sé dónde reemplazarlo, porque si el observador de 'contenido' reemplaza el contenido, la devolución de llamada se enviará nuevamente, y nuevamente, y nuevamente, ... – louiscoquio

+0

Ver mi actualización. Resuelve ese problema. –

+0

¡funciona! Ya lo intenté, pero llamé a 'this._super()' antes de ordenar el contenido para que no funcionara. De todos modos, gracias – louiscoquio

Cuestiones relacionadas