简体   繁体   English

灰烬路由器动态路由

[英]Ember Router dynamic route

I have some kind of a "dash view" with a subset of items displayed. 我有某种“破折号视图”,其中显示了部分项目。 The item may "toggled" (by some navigation) for display in the main outlet. 该项目可能会“切换”(通过某种导航)以显示在主插座中。 So far I lived without Ember's Router / StateManager stuff but instead I serialized/deserialized the URL manually and used window.history to enable back/foward and "restore by URL" features. 到目前为止,我没有Ember的Router / StateManager东西,而是手动对URL进行序列化/反序列化,并使用window.history启用后退/转发和“按URL还原”功能。 eg 例如

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

should display the foo, bar and ted elements respectively. 应该分别显示foo,bar和ted元素。 The items may be lazy loaded in the background. 这些项目可能会在后台延迟加载。 So if you restore the app state by bookmarking/directly editing the URL, the items actually may arrive some time later. 因此,如果您通过添加书签/直接编辑URL来恢复应用状态,则这些项目实际上可能会在一段时间后到达。

I try to employ Ember.Router for this stuff, but I just dont get it working... 我尝试使用Ember.Router来完成这些工作,但我只是不起作用而已...

I read through this great guide http://emberjs.com/guides/router_primer/ . 我通读了这份出色的指南http://emberjs.com/guides/router_primer/ But the scenario described is always like: you have a collection view and a single item view. 但是所描述的场景总是像:您有一个集合视图和一个项目视图。 But that does not apply for my app. 但这不适用于我的应用程序。

In this scenario I have 3 items and I want to select some of them for display in the outlet, by toggling them. 在这种情况下,我有3个项目,并且希望通过切换它们来选择其中一些以显示在插座中。 (In general this could be selecting,unselecting,toggling or search-by-expression). (通常,这可以是选择,取消选择,切换或按表达式搜索)。 The selected-items-in-dash-state should be serialized to URL and be restorable by bookmarking or directly modyfing the URL. 选中项在短划线状态应序列化为URL,并可以通过添加书签或直接修改URL来恢复。

Toggling is implemented like this: 切换是这样实现的:

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

This is how the data fetching and selection logic is right now (ITS NOT WORKING THOUGH) 这就是现在的数据获取和选择逻辑的方式(无法正常工作)

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

And that is the router: 那就是路由器:

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

This is the complete fiddle http://jsfiddle.net/NWfbj/1 这是完整的小提琴http://jsfiddle.net/NWfbj/1

Any help is very appreciated! 任何帮助都非常感谢!

Well, I try to fix some things: 好吧,我尝试解决一些问题:

  • when accessing properties in an Ember oject, a good rule is to always use get('property')/set('property',value') 访问Ember对象中的属性时,一个好的规则是始终使用get('property')/ set('property',value')

  • When you want to observe arrays content, use the special '@each'. 当您要观察数组内容时,请使用特殊的“ @each”。 The observer is then triggered when any object in the array is added/removed. 然后在添加/删除数组中的任何对象时触发观察者。

  • I removed what I thought an extra items.clear() in the items() function. 我删除了我认为在items()函数中多余的items.clear()的东西。

If you want to be able to manipulate through the URL, I think you have to review the deserialize method, in order to return what you expect (I don't know if it should be string array, an array of items (retrieved from the store), it's up to you :) 如果您希望能够通过URL进行操作,那么我认为您必须查看反序列化方法,才能返回期望的结果(我不知道它是否应该是字符串数组,项目数组(从店),这取决于您:)

You can see what I've done here: http://jsfiddle.net/Sly7/NWfbj/23/ 您可以在这里查看我的操作: 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM