2

Ember でブログ アプリケーションを構築しようとしています。記事、ブックマーク、写真など、さまざまなタイプの投稿のモデルがあります。ユーザーが作成したコンテンツのストリームを表示したいのですが、これらすべてのモデルのオブジェクトのコレクションが必要であり、それらがすべて「publishtime」を持つ共通属性の降順で配置されています。これを行う方法?

私は次のようなものを試しました

App.StreamRoute = Ember.Route.extend({
    model: function() {
        stream = App.Post.find();
        stream.addObjects(App.Bookmark.find());
        stream.addObjects(App.Photo.find());
        return stream;
    }
}

リソース名の場所stream

しかし、うまくいきません。最新リリースの Ember 1.0.0 rc 2 とハンドルバー 1.0.0 rc 3 を jQuery 1.9.1 と ember-data で使用しています。

おそらく、私がこのすべてを達成しようとしている方法は間違っています。問題は、複数のモデルのオブジェクトのコレクションを使用してテンプレートを反復処理できたとしても、「publishtime」の共通プロパティとは別にプロパティを表示するために、各オブジェクトのタイプを区別する必要があることです。

4

2 に答える 2

4

計算されたプロパティを使用してさまざまな配列を組み合わせてから、Javascript の組み込みの並べ替えを使用して、組み合わせた結果を並べ替えることができます。

配列を結合して並べ替える

複数の配列を結合するための計算されたプロパティ:

  stream: function() {
    var post = this.get('post'),
        bookmark = this.get('bookmark'),
        photo = this.get('photo');

    var stream = [];

    stream.pushObjects(post);
    stream.pushObjects(bookmark);
    stream.pushObjects(photo);
    return stream;
  }.property('post.@each', 'bookmark.@each', 'photo.@each'),

すべての項目を含む結果の計算されたプロパティを並べ替える例:

  //https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort
  streamSorted: function() {
    var streamCopy = this.get('stream').slice(); // copy so the original doesn't change when sorting
    return streamCopy.sort(function(a,b){
      return a.get('publishtime') - b.get('publishtime');
    });
  }.property('stream.@each.publishtime')
});

プロパティまたはそのタイプに基づいてアイテムをレンダリングする

私はこれを行う2つの方法を知っています:

  1. 各オブジェクトにブール値のプロパティを追加し、ハンドルバーを使用し{{#if}}てそのプロパティをチェックし、正しいビューをレンダリングします
  2. 計算されたプロパティを拡張Ember.Viewして使用し、レンダリングされるオブジェクトのタイプに基づいてレンダリングされるテンプレートを切り替えます ( Ember.js を使用してモデル タイプ/オブジェクト値によってビュー テンプレートを選択するに基づく)

方法 1

JS:

App.Post = Ember.Object.extend({
  isPost: true
});

App.Bookmark = Ember.Object.extend({
  isBookmark: true
});

App.Photo = Ember.Object.extend({
  isPhoto: true
});

テンプレート:

<ul>
  {{#each item in controller.stream}}
      {{#if item.isPost}}
        <li>post: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
      {{#if item.isBookmark}}
        <li>bookmark: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
      {{#if item.isPhoto}}
        <li>photo: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
  {{/each}}
   </ul>

方法 2

JS:

App.StreamItemView = Ember.View.extend({
  tagName: "li",
  templateName: function() {
    var content = this.get('content');
    if (content instanceof App.Post) {
      return "StreamItemPost";
    } else if (content instanceof App.Bookmark) {
      return "StreamItemBookmark";
    } else if (content instanceof App.Photo) {
      return "StreamItemPhoto";
    }
  }.property(),

  _templateChanged: function() {
        this.rerender();
    }.observes('templateName')
})

テンプレート:

<ul>
{{#each item in controller.streamSorted}}
    {{view App.StreamItemView contentBinding=item}}
{{/each}}
 </ul>

JSBinの例 - ソートされていないリストはメソッド 1 でレンダリングされ、ソートされたリストはメソッド 2 でレンダリングされます

于 2013-04-08T01:31:47.277 に答える
0

それより少し複雑ですが、@twinturbo の例は、個別のモデルを 1 つの配列に集約する方法をうまく示しています。

集約配列プロキシを示すコード:

App.AggregateArrayProxy = Ember.ArrayProxy.extend({
    init: function() {
        this.set('content', Ember.A());
        this.set('map', Ember.Map.create());
    },

    destroy: function() {
        this.get('map').forEach(function(array, proxy) {
            proxy.destroy();
        });

        this.super.apply(this, arguments);
    },

    add: function(array) {
        var aggregate = this;

        var proxy = Ember.ArrayProxy.create({
            content: array,
            contentArrayDidChange: function(array, idx, removedCount, addedCount) { 
                var addedObjects = array.slice(idx, idx + addedCount);

                addedObjects.forEach(function(item) {
                    aggregate.pushObject(item);
                });
            },
            contentArrayWillChange: function(array, idx, removedCount, addedCount) { 
                var removedObjects = array.slice(idx, idx + removedCount);

                removedObjects.forEach(function(item) {
                    aggregate.removeObject(item);
                });
            }
        });

        this.get('map').set(array, proxy);
    },

    remove: function(array) {
        var aggregate = this;

        array.forEach(function(item) {
            aggregate.removeObject(item);
        });

        this.get('map').remove(array);
    }
});
于 2013-04-07T20:35:13.060 に答える