EmberJS: Cómo cargar varios modelos en la misma ruta?


Si bien no soy nuevo en el desarrollo web, soy bastante nuevo en los marcos MVC del lado del cliente. Investigué un poco y decidí intentarlo con EmberJS. Pasé por la guía TodoMVC y tenía sentido para mí...

He configurado una aplicación muy básica; ruta de índice, dos modelos y una plantilla. Tengo un script php del lado del servidor en ejecución que devuelve algunas filas de bd.

Una cosa que me confunde mucho es cómo cargar varios modelos en la misma ruta. He leído alguna información sobre el uso de un setupController pero todavía no estoy claro. En mi plantilla tengo dos tablas que estoy tratando de cargar con desconocidas db filas. En una aplicación web más tradicional, solo habría emitido instrucciones sql y loopeado sobre ellas para llenar las filas. Estoy teniendo dificultades para traducir este concepto a EmberJS.

¿Cómo puedo cargar varios modelos de datos no relacionados en la misma ruta?

Estoy usando las últimas liberaciones de datos de Ember y Ember.

Actualizar

Aunque la primera respuesta da un método para manejarlo, la segunda respuesta explica cuándo es apropiado y los diferentes métodos para cuando no es apropiado.

Author: Kingpin2k, 2013-12-11

5 answers

Puedes usar la brasa .RSVP.hash para cargar varios modelos:

app/routes/index.js

import Ember from 'ember';

export default Ember.Route.extend({
  model() {
    return Ember.RSVP.hash({
      people: this.store.findAll('person'),
      companies: this.store.findAll('company')
    });
  },

  setupController(controller, model) {
    this._super(...arguments);
    Ember.set(controller, 'people', model.people);
    Ember.set(controller, 'companies', model.companies);
  }
});

Y en su plantilla puede referirse a people y companies para obtener los datos cargados:

app/templates/index.js

<h2>People:</h2>
<ul>
  {{#each people as |person|}}
    <li>{{person.name}}</li>
  {{/each}}
</ul>
<h2>Companies:</h2>
<ul>
  {{#each companies as |company|}}
    <li>{{company.name}}</li>
  {{/each}}
</ul>

Esto es un giro con esta muestra: https://ember-twiddle.com/c88ce3440ab6201b8d58

 92
Author: Marcio Junior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-14 22:33:41

CUIDADO:

Debe tener cuidado acerca de si es apropiado o no devolver varios modelos en su gancho de modelo. Hágase esta simple pregunta:

  1. ¿Mi ruta carga datos dinámicos basados en la url usando un slug :id? i. e. this.resource('foo', {path: ':id'});

Si usted respondió sí

No intente cargar varios modelos desde el gancho modelo en esa ruta!!! La razón radica en la forma en que Ember maneja los enlaces a las rutas. Si usted proporciona un modelo cuando se enlaza a esa ruta ({{link-to 'foo' model}}, transitionTo('foo', model)) se saltará el gancho modelo y utilizar el modelo suministrado. Esto es probablemente problemático ya que esperaba varios modelos, pero solo se entregaría un modelo. Aquí hay una alternativa:

Hazlo en setupController / afterModel

App.IndexRoute = Ember.Route.extend({
  model: function(params) {
    return $.getJSON('/books/' + params.id);
  },
  setupController: function(controller, model){
    this._super(controller,model);
    controller.set('model2', {bird:'is the word'});
  }
});

Ejemplo: http://emberjs.jsbin.com/cibujahuju/1/edit

Si lo necesitas para bloquear la transición (como lo hace el gancho del modelo) devuelve una promesa del gancho afterModel. Usted tendrá que mantener manualmente rastrea los resultados de ese gancho y conéctalos a tu controlador.

App.IndexRoute = Ember.Route.extend({
  model: function(params) {
    return $.getJSON('/books/' + params.id);
  },
  afterModel: function(){
    var self = this;
    return $.getJSON('/authors').then(function(result){
      self.set('authors', result);
    });
  }, 
  setupController: function(controller, model){
    this._super(controller,model);
    controller.set('authors', this.get('authors'));
  }
});

Ejemplo: http://emberjs.jsbin.com/diqotehomu/1/edit

Si usted respondió no

Adelante, devolvamos varios modelos desde el gancho del modelo de la ruta:

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return {
           model1: ['red', 'yellow', 'blue'],
           model2: ['green', 'purple', 'white']
    };
  }
});

Ejemplo: http://emberjs.jsbin.com/tuvozuwa/1/edit

Si es algo que necesita ser atendido (como una llamada al servidor, algún tipo de promesa)

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return Ember.RSVP.hash({
           model1: promise1,
           model2: promise2
    });
  }
});

Ejemplo: http://emberjs.jsbin.com/xucepamezu/1/edit

En el caso de Ember Data

App.IndexRoute = Ember.Route.extend({
  var store = this.store;
  model: function() {
    return Ember.RSVP.hash({
           cats: store.find('cat'),
           dogs: store.find('dog')
    });
  }
});

Ejemplo: http://emberjs.jsbin.com/pekohijaku/1/edit

Si uno es una promesa, y el otro no lo es, todo está bien, RSVP con gusto solo usará ese valor{[17]]}

App.IndexRoute = Ember.Route.extend({
  var store = this.store;
  model: function() {
    return Ember.RSVP.hash({
           cats: store.find('cat'),
           dogs: ['pluto', 'mickey']
    });
  }
});

Ejemplo: http://emberjs.jsbin.com/coxexubuwi/1/edit

Mezclar y combinar y divertirse!

App.IndexRoute = Ember.Route.extend({
  var store = this.store;
  model: function() {
    return Ember.RSVP.hash({
           cats: store.find('cat'),
           dogs: Ember.RSVP.Promise.cast(['pluto', 'mickey']),
           weather: $.getJSON('weather')
    });
  }, 
  setupController: function(controller, model){
    this._super(controller, model);
    controller.set('favoritePuppy', model.dogs[0]);
  }
});

Ejemplo: http://emberjs.jsbin.com/joraruxuca/1/edit

 149
Author: Kingpin2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-07 02:55:17

Utilizo algo como la respuesta que Marcio proporcionó pero se ve algo como esto:

    var products = Ember.$.ajax({
        url: api + 'companies/' +  id +'/products',
        dataType: 'jsonp',
        type: 'POST'
    }).then(function(data) {
        return data;
    });

    var clients = Ember.$.ajax({
        url: api + 'clients',
        dataType: 'jsonp',
        type: 'POST'
    }).then(function(data) {
        return data;
    });

    var updates = Ember.$.ajax({
        url: api + 'companies/' +  id + '/updates',
        dataType: 'jsonp',
        type: 'POST'
    }).then(function(data) {
        return data;
    });

    var promises = {
        products: products,
        clients: clients,
        updates: updates
    };

    return Ember.RSVP.hash(promises).then(function(data) {
      return data;
    });  
 3
Author: la_antorcha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-08 14:37:30

Si utiliza Datos Ember, se vuelve aún más simple para modelos no relacionados:

import Ember from 'ember';
import DS from 'ember-data';

export default Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller,model);
    var model2 = DS.PromiseArray.create({
      promise: this.store.find('model2')
    });
    model2.then(function() {
      controller.set('model2', model2)
    });
  }
});

Si solo desea recuperar la propiedad de un objeto para model2, utilice DS.PromiseObject en lugar de DS.PromiseArray :

import Ember from 'ember';
import DS from 'ember-data';

export default Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller,model);
    var model2 = DS.PromiseObject.create({
      promise: this.store.find('model2')
    });
    model2.then(function() {
      controller.set('model2', model2.get('value'))
    });
  }
});
 2
Author: AWM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-05 13:53:48

La última versión de JSON-API implementada en Ember Data v1.13 admite la agrupación de diferentes recursos en la misma solicitud muy bien, si no le importa modificar sus puntos finales de API.

En mi caso, tengo un punto final session. La sesión se relaciona con un registro de usuario, y el registro de usuario se relaciona con varios modelos que siempre quiero cargar en todo momento. Es muy agradable que todo venga con una sola petición.

Una advertencia por la especificación es que todos los las entidades que devuelvas deben estar vinculadas de alguna manera a la entidad principal que se recibe. Creo que ember-data solo atravesará las relaciones explícitas al normalizar el JSON.

Para otros casos, ahora estoy eligiendo diferir la carga de modelos adicionales hasta que la página ya esté cargada, es decir, para paneles de datos separados o lo que sea, por lo menos la página se representa lo más rápido posible. Al hacer esto, hay alguna pérdida / cambio con el estado de carga de error" automático " que debe ser considerar.

 2
Author: aceofspades,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-05 17:02:02