web-dev-qa-db-ja.com

EmberJS:複数のモデルを同じルートにロードする方法は?

私はWeb開発には慣れていませんが、クライアント側のMVCフレームワークにはまったく慣れていません。私はいくつかの調査を行い、EmberJSで試してみることにしました。 TodoMVCガイドを読みましたが、それは理にかなっています...

非常に基本的なアプリをセットアップしました。インデックスルート、2つのモデル、1つのテンプレート。いくつかのdb行を返すサーバー側のphpスクリプトを実行しています。

私を非常に混乱させているのは、同じルートに複数のモデルをロードする方法です。 setupControllerの使用に関するいくつかの情報を読みましたが、まだわかりません。テンプレートには、無関係なdb行でロードしようとしている2つのテーブルがあります。より伝統的なWebアプリでは、SQLステートメントに対して発行し、それらをループして行を埋めていました。この概念をEmberJSに翻訳するのに苦労しています。

関係のないデータの複数のモデルを同じルートに読み込むにはどうすればよいですか?

最新のEmberおよびEmber Data libsを使用しています。

更新

最初の答えはそれを処理する方法を提供しますが、2番目の答えはそれが適切な場合と、適切でない場合のさまざまな方法を説明します。

74
Eric

Ember.RSVP.hash を使用して、いくつかのモデルをロードできます。

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

テンプレートでpeopleおよびcompaniesを参照して、ロードされたデータを取得できます。

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>

これは、このサンプルのTwiddleです。 https://ember-twiddle.com/c88ce3440ab6201b8d58

93
Marcio Junior

注意してください:

モデルフックで複数のモデルを返すことが適切かどうかに注意する必要があります。次の簡単な質問を自問してください。

  1. ルートは、スラッグ_:id_を使用してURLに基​​づいて動的データをロードしますか?すなわちthis.resource('foo', {path: ':id'});

はいと答えた場合

そのルートのモデルフックから複数のモデルをロードしようとしないでください!!!理由はEmber =ルートへのリンクを処理します。そのルート(_{{link-to 'foo' model}}_、transitionTo('foo', model))へのリンク時にモデルを提供すると、モデルフックがスキップされ、提供されたモデルが使用されます。複数のモデルがありますが、配信されるモデルは1つだけです。

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

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

(モデルフックのように)遷移をブロックする必要がある場合は、afterModelフックからプロミスを返します。そのフックからの結果を手動で追跡し、コントローラーに接続する必要があります。

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

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

いいえと答えた場合

先に進み、ルートのモデルフックから複数のモデルを返しましょう。

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

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

待機する必要があるものである場合(サーバーへの呼び出し、何らかの約束など)

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

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

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

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

一方が約束でもう一方がそうでない場合、それはすべて良いことです。RSVPは喜んでその値を使用します

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

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

組み合わせて楽しんでください!

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

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

149
Kingpin2k

私はマルシオが提供した答えのようなものを使用しますが、それは次のように見えます:

    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
la_antorcha

Ember Dataを使用すると、関係のないモデルではさらに簡単になります。

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

model2のオブジェクトのプロパティのみを取得する場合は、 DS.PromiseArray の代わりに DS.PromiseObject を使用します。

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
AWM

最新バージョンの JSON-API Ember Data v1.13は、同じリクエストで異なるリソースのバンドルを非常によくサポートします。 APIエンドポイント。

私の場合、sessionエンドポイントがあります。セッションはユーザーレコードに関連し、ユーザーレコードは常にロードする必要があるさまざまなモデルに関連しています。 1つのリクエストですべてを受信できるのは非常に素晴らしいことです。

仕様ごとの1つの注意点は、返されるすべてのエンティティを、受信するプライマリエンティティに何らかの形でリンクする必要があるということです。 JSONを正規化するとき、ember-dataは明示的な関係のみをトラバースすると信じています。

他のケースでは、ページが既にロードされるまで、つまりデータの別のパネルなどに追加のモデルのロードを延期することを選択しているため、少なくともページは可能な限り迅速にレンダリングされます。これを行うと、考慮すべき「自動」エラー読み込み状態に何らかの損失/変更があります。

2
aceofspades