如何在ember中重定向到具有对象的路径?

时间:2013-02-18 14:40:42

标签: javascript ember.js ember-router

我正在尝试在Ember.js中组建一个数据驱动的菜单系统。这是javascript,js/nodal.js

window.Form = Ember.Application.create();

var menuOptions = [
{id: "root",
 options: [ "a", "b" ]},
{id: "a",
      name: "Option A",
 options: [ "c", "d" ]},
{id: "b",
  name: "Option B",
 options: [ "e", "f" ]},
{id: "c",
 name: "Option C"},
{id: "d",
 name: "Option D"},
{id: "e",
 name: "Option E"},
{id: "f",
 name: "Option F"}
]

Form.MenuOption = Ember.Object.extend({});

var builtOptions = menuOptions.map( function(attrs) {
return Form.MenuOption.create( attrs );
});

Form.options = {};
for( i = 0; i < builtOptions.length; i++ ) {
var opt = builtOptions[i];
Form.options[opt.id] = opt;
}

Form.MenuRoute = Ember.Route.extend({
model: function(params){
    console.log( params );
    if( !params || !params.index_id || params.index_id == "undefined") {
    params.index_id = "root";
    }
    var keys = Form.options[params.index_id].options;
    var options = new Array();
    keys.map(function(k){ options.push( Form.options[k] ); });
    return options;
  }    
});

Form.IndexRoute = Ember.Route.extend({
redirect: function(){
        /* This here is the problem line... */
    this.transitionTo( "menu", Form.options.root );
}
});

Form.Router.map(function(){
this.resource( "menu", { path: "/menu/:index_id" } );
});

这是HTML,例如:

                                                  

  <title>Hello</title>
  <meta name="description" content="My First Ember.js App">
  <meta name="author" content="Your Name Here">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <script data-template-name="application" type="text/x-handlebars">
<h1>Title Goes Here</h1>
{{outlet}}
  </script>


  <script data-template-name="menu" type="text/x-handlebars">
<ul>
{{#each controller}}
  <li>{{#linkTo menu this}}{{name}}{{/linkTo}}</li>
{{/each}}
</ul>
  </script>


  <script src="js/libs/jquery-1.9.1.js"></script>
  <script src="js/libs/handlebars.js"></script>
  <script src="js/libs/ember-1.0.0-rc.1.js"></script>
  <script src="js/nodal.js"></script>
</body>
</html>

我想要的是让用户在打开页面后立即重定向到/menu/root。到目前为止,我还没有找到合适的咒语来完成这项工作。当我加载上面的内容时,我得到了这个例外:

Error: assertion failed: an Ember.CollectionView's content must implement Ember.Array. You passed <(generated menu controller):ember172>

如果我直接加载index.html#/menu/root,它就可以运行 - 它只是重定向不起作用。用以下代码替换IndexRoute定义中的this.transitionTo行:

this.transitionTo( "menu", [Form.options.root] );

执行重定向,但重定向到/menu/undefined,而不是/menu/root。那很难看,而且很明显坏了。

我错过了什么?

修改

正如所建议的那样,我尝试添加一个ArrayController:

Form.MenuController = Ember.ArrayController.extend({});

这给了我一个新的错误:

arrangedContent.addArrayObserver is not a function

2 个答案:

答案 0 :(得分:0)

错误消息基本上表示视图要求数组或数组控制器作为视图的内容,而是接收生成的控制器(当没有为路由定义控制器时生成控制器)。路由的model方法返回数组,因此必须使用适当的控制器包裹ArrayController。您应该为扩展ArrayController菜单路由定义自定义控制器 - 这将消除错误消息。

修改

关于路由:我认为您应该将每个菜单选项定义为嵌套在菜单资源中的路由,如下所示:

Form.Router.map(function(){
    this.resource( "menu", { path: "/menu/:index_id" }, function () {
        this.route('root');
        this.route('a');
        this.route('b');
        ...
    });
});

这还需要为每条路线定义 Route 类。

答案 1 :(得分:0)

问题是您的URL假定您正在使用一个模型,但在transitioTo和您的模型钩子中您传递/返回一个数组。您的MenuRoute始终是一个 MenuOption,对吧?

因此我建议:

Form.MenuRoute = Ember.Route.extend({
model: function(params){
    console.log( params );
    if( !params || !params.index_id || params.index_id == "undefined") {
    params.index_id = "root";
    }
    var menuOption = Form.options[params.index_id];
    return menuOption;
  }    
});

在这种情况下,您的相应模板应该如下所示:

<script data-template-name="menu" type="text/x-handlebars">
<ul>
{{#each option in controller.content.options}}
  <li>{{#linkTo menu option}}{{option.name}}{{/linkTo}}</li>
{{/each}}
</ul>
</script>