0

アイテムのサブセットが表示されたある種の「ダッシュ ビュー」があります。項目は、メイン アウトレットに表示するために (何らかのナビゲーションによって) 「トグル」される場合があります。これまでのところ、私は Ember の Router / StateManager なしで生活していましたが、代わりに手動で URL をシリアル化/逆シリアル化し、window.history を使用して戻る/進むおよび「URL による復元」機能を有効にしました。例えば

#/dash/foo,bar 
#/dash/foo,bar,ted

foo、bar、ted 要素をそれぞれ表示する必要があります。項目はバックグラウンドで遅延ロードされる場合があります。そのため、URL をブックマーク/直接編集してアプリの状態を復元すると、アイテムが実際に到着するのはしばらく後になる場合があります。

このために Ember.Router を使用しようとしていますが、うまくいきません...

このすばらしいガイドhttp://emberjs.com/guides/router_primer/を読みました。しかし、ここで説明するシナリオは常に似ています: コレクション ビューと単一アイテム ビューがあります。しかし、それは私のアプリには当てはまりません。

このシナリオでは、3 つのアイテムがあり、それらのいくつかを切り替えてアウトレットに表示するように選択したいと考えています。(一般に、これは選択、選択解除、トグル、または式による検索である可能性があります)。selected-items-in-dash-state は URL にシリアル化され、URL をブックマークするか直接変更することで復元できる必要があります。

トグルは次のように実装されます。

<a {{action toggle name href=true}}>{{name}}</a>

これは、データの取得と選択のロジックが現在どのようになっているかです (それは機能していません)

App.dash = Ember.Object.create({
    FIXTURE: [App.Item.create({
        name: 'foo',
        detail: 'Some very interesting foo'
    }),App.Item.create({
        name: 'bar',
        detail: 'Bar is the root of all stuff'
    }),App.Item.create({
        name: 'ted',
        detail: 'Ted is not my name'
    })],
    store: Ember.A(),
    selected: Ember.A(),
    _items: Ember.A(),
    watchItems: function () {
        var items = this._items;
        var store = this.store;
        items.clear();
        this.get('selected').forEach(function (name) {
            var item = store.findProperty('name', name);
            items.pushObject(item);
        });
    }.observes('selected', 'store'),
    toggle: function (name) {
        var selected = this.get('selected');
        var index = selected.indexOf(name);
        if (index !== -1) {
            selected.removeAt(index);
        } else {
            selected.push(name);
        }
        this.set('selected', selected);
    },
    fetch: function () {
        var FIXTURE = this.FIXTURE;
        var store = this.store;
        if (store.length == 0) {
            Ember.run.later(function () {
                FIXTURE.forEach(function (item) {
                    store.pushObject(item);
                });
            }, 2000);
        }
    },        
    items: function (selected) {
        var items = this._items;
        items.clear();
        if (Ember.isArray(selected)) {
            this.set('selected', selected);
        } else {
            this.set('selected', []);
        }
        this.fetch();
        return items;
    }
});

そして、それがルーターです:

 App.Router = Ember.Router.extend({
    root: Ember.Route.extend({
        index: Ember.Route.extend({
            route: '/',
            redirectsTo: 'dash'
        }),
        dash: Ember.Route.extend({
            route: '/dash/:selected',
            connectOutlets: function (router, context) {
                var selected = context && context.selected;
                var dashItems = App.dash.items(selected);
                router.get('applicationController').connectOutlet('dash', dashItems);
            },
            deserialize: function (router, params) {
                if (params.selected !== 'undefined') {
                    return params.selected;
                }
            },
            serialize: function (router, context) {
                var selected = App.dash.get('selected');
                var hash = {
                    selected: selected
                };
                return hash;
            },
            toggle: function (router, event) {
                event.preventDefault();
                event.stopPropagation();
                var name = event.context;
                App.dash.toggle(name);
                var selected = App.dash.get('selected');
                router.transitionTo('dash', {
                    selected: selected
                });
            },
            eventTransitions: {
                toggle: 'dash'
            }
        })
    })
});

これは完全なフィドルですhttp://jsfiddle.net/NWfbj/1

どんな助けでも大歓迎です!

4

1 に答える 1

1

さて、私はいくつかのことを修正しようとします:

  • Emberオブジェクトのプロパティにアクセスするときは、常にget('property')/ set('property'、value')を使用することをお勧めします。

  • 配列の内容を監視する場合は、特別な「@each」を使用します。配列内のオブジェクトが追加/削除されると、オブザーバーがトリガーされます。

  • items()関数の余分なitems.clear()を削除しました。

URLを操作できるようにしたい場合は、期待どおりの結果を返すために、deserializeメソッドを確認する必要があると思います(文字列配列、アイテムの配列(から取得)ストア)、それはあなた次第です:)

あなたは私がここでしたことを見ることができます:http://jsfiddle.net/Sly7/NWfbj/23/

<script type="text/x-handlebars" data-template-name='application'>
  <h1>Dash Router App</h1>
  {{#each App.dash.store}}
  <a {{action toggle name href=true}}>{{name}}</a>
  {{/each}}
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name='dash'>
   {{#each controller}}
    <h1>{{detail}}</h1>
   {{/each}}
</script>
App = Ember.Application.create();
App.Item = Ember.Object.extend({
    name: null,
    detail: null
});

App.dash = Ember.Object.create({
    FIXTURE: [{
        name: 'foo',
        detail: 'Some very interesting foo'
    }, {
        name: 'bar',
        detail: 'Bar is the root of all stuff'
    }, {
        name: 'ted',
        detail: 'Ted is not my name'
    }],
    store: [],

    selected: [],

    _items: [],

    watchItems: function () {
        console.log('watch items', this.get('selected'));
        var self = this;
        this.get('_items').clear();
        this.get('selected').forEach(function (name) {
            var item = self.get('store').findProperty('name', name);
            console.log(name);
            self.get('_items').pushObject(item);
        });
    }.observes('selected.@each', 'store.@each'),

    toggle: function (name) {
        var selected = this.get('selected');
        var index = selected.indexOf(name);
        if (index !== -1) {
            selected.removeObject(name);
        } else {
            selected.pushObject(name);
        }
        console.log('toggle', name, 'is now selected?', selected.indexOf(name) !== -1, selected);
        this.set('selected', selected);
    },

    fetch: function () {
        var FIXTURE = this.get('FIXTURE');
        var store = this.get('store');
        if (store.length == 0) {
            Ember.run.later(function () {
                FIXTURE.forEach(function (item) {
                    store.pushObject(item);
                });
            }, 2000);
        }
    },  

    items: function (selected) {
        if (Ember.isArray(selected)) {
            this.set('selected', selected);
        } else {
            this.set('selected', []);
        }
        this.fetch();
        return this.get('_items');
    }
});
App.ApplicationController = Ember.Controller.extend({});
App.ApplicationView = Ember.View.extend({
    templateName: 'application'
});
App.DashView = Ember.View.extend({
    templateName: 'dash'
});
App.DashController = Ember.ArrayController.extend({});

App.Router = Ember.Router.extend({
    enableLogging: true,
    root: Ember.Route.extend({
        index: Ember.Route.extend({
            route: '/',
            redirectsTo: 'dash'
        }),
        dash: Ember.Route.extend({
            enter: function () {
                console.log('entering dash');
            },
            exit: function () {
                console.log('exiting dash');
            },
            route: '/dash/:selected',
            connectOutlets: function (router, context) {
                debugger;
                var selected = context && context.selected;
                console.log('connectOutlets', 'selected:', selected);
                var dashItems = App.dash.items(selected);
                console.log('connectOutlets', dashItems);
                router.get('applicationController').connectOutlet('dash', dashItems);
            },
            deserialize: function (router, params) {
                debugger;
                console.log('deserialize', 'selected:', params.selected);
                if (params.selected !== 'undefined') {
                    return params.selected;
                }
            },
            serialize: function (router, context) {
                var selected = App.dash.get('selected');
                var hash = {
                    selected: selected
                };
                console.log('serialize', 'selected:', selected);
                return hash;
            },
            toggle: function (router, event) {
                debugger;
                event.preventDefault();
                event.stopPropagation();
                var name = event.context;
                console.log('clicked',name);
                App.dash.toggle(name);
                var selected = App.dash.get('selected');
                console.log('transitionTo', 'selected:', selected);
                router.transitionTo('dash', {
                    selected: selected
                });
            },
            eventTransitions: {
                toggle: 'dash'
            }
        })
    })
});
App.initialize();
于 2012-10-19T08:44:41.487 に答える