2

任务:

在灯箱中打开表单以创建新的“事件”;打开的表格应该可以收藏。

路障:

  1. 有使用{{action}}标签打开灯箱的示例,但找不到以自己的路线打开的灯箱。
  2. 有许多使用旧版本 ember.js 的示例。
  3. 没有很多与 ember-data 和 REST 相关的文档(我知道,我知道......它还没有“准备好生产”)。

问题:

表单中的字段没有绑定到支持模型,因此“null”被发布到我的 servlet(一个 Spring 控制器)。

我的第一次迭代与最终结果(jsfiddle)相差不远。最终使它起作用的东西交换了这个:

EP.EventsNewRoute = Ember.Route.extend({
    ...
    setupController : function(controller, model) {
        controller.set("model", model);
    },
    ...
});

...为了这:

EP.EventsNewRoute = Ember.Route.extend({
    ...
    setupController : function(controller, model) {
        this.controllerFor("events-new").set("model", model);
    },
    ...
});

问题:

为什么需要调用 setupController 函数controllerFor才能正确设置模型?


最后,由于我很难找到一个功能齐全的示例,我想让它易于访问(并希望发现改进)。

这是小提琴:http: //jsfiddle.net/6thJ4/1/

这里有几个片段。

HTML:

<script type="text/x-handlebars">
    <div>
        <ul>
            {{#linkTo "events.new" tagName="li"}}
            Add Event
            {{/linkTo}}
        </ul>
    </div>
    {{outlet events-new}}
</script>
<script type="text/x-handlebars" data-template-name="events-new">
    <form>
        <div>
            <label>Event Name:</label>
            {{view Ember.TextField valueBinding="name"}}
        </div>
        <div>
            <label>Host Name:</label>
            {{view Ember.TextField valueBinding="hostName"}}
        </div>
    </form>
</script>

JavaScript:

...
EP.Router.map(function() {
    this.resource("events", function() {
        this.route("new");
    });
});
EP.EventsNewRoute = Ember.Route.extend({
    model : function() {
        return EP.Event.createRecord();
    },
    setupController : function(controller, model) {
        //controller.set("model", model); // Doesn't work? Why not?
        this.controllerFor("events-new").set("model", model); // What does this do differently?
    },
    ...
});
EP.EventsNewController = Ember.ObjectController.extend({
    save : function() {
        this.get("content.transaction").commit(); // "content.store" would commit _everything modified_, we only have one element changed, so only "content.transaction" is necessary.
    }
});
EP.EventsNewView = Ember.View.extend({
...
});
EP.Event = DS.Model.extend({
    name : DS.attr("string"),
    hostName : DS.attr("string")
});

资源:

  1. http://emberjs.com/guides/routing/setting-up-a-controller/
  2. http://emberjs.com/guides/getting-started/toggle-all-todos/(试图模仿我学到的东西,但是将添加新的东西变成新的路线)
  3. 编写 LightboxView 会导致问题/集成 DOM 操作 jQuery-Plugins 使操作无法使用(灯箱“示例”)
  4. Ember 中的可靠视图(另一个灯箱“示例”,但没有打开灯箱的路线)
4

1 回答 1

2

为什么 setupController 函数需要调用 controllerFor 才能正确设置模型?

Ember 使 URL 成为其约定中不可或缺的一部分。这意味着state您的应用程序的 由它所在的路由表示。您已经正确理解了其中的大部分内容。但是有几个微妙的细微差别,我将在下面澄清。

首先考虑一个具有以下 URL 的应用,

  • /posts - 显示博客文章列表。
  • /posts/1 - 显示单个博客文章。

并说单击列表中的帖子/posts会将您带到/posts/1

在这种情况下,用户可以通过 2 种方式在/posts/1.

  1. 通过转到/posts并单击第一个帖子。
  2. 通过输入/posts/1,通过书签等。

在这两种情况下,PostRoutefor/posts/1都需要对应于Postid 1 的模型。

首先考虑直接输入场景。为了提供一种查找 id=1 后模型的方法,您可以使用,

model: function(params) {
  return App.Post.find(params.post_id);
}

您的帖子模板将获取模型,并且可以使用其属性进行渲染。

现在考虑第二种情况。单击 id=1 的帖子会将您带到/posts/1. 为此,您的模板将linkTo像这样使用。

{{#linkTo 'post' post}} {{post.title}} {{/linkTo}}

在这里,您将post模型传递给linkTo助手。然后它将帖子的数据序列化为 URL,即:-'/posts/1'。当您单击此链接时,Ember 意识到它需要渲染,PostRoute但它已经有了 post 模型。所以它跳过模型钩子并直接调用setupController.

默认setupController设置为简单地在控制器上分配模型。它的实现是为了做类似的事情,

setupController: function(controller, model) {
  controller.set('model', model);
}

如果您不需要在控制器上设置自定义属性,则不需要覆盖它。注意:如果您使用其他属性对其进行扩充,您仍然需要调用_super以确保执行默认的 setupController 行为。

setupController: function(controller, model) {
  this._super.apply(this, arguments);
  controller.set('customProp', 'foo');
}

最后一个警告,如果您正在使用linkTo并且路线没有dynamic segments,那么仍然会调用模型挂钩。如果您认为您正在链接到该/posts路线,则此例外是有意义的。然后模型钩子必须触发,否则 Ember 没有数据来显示路线。

这让我们找到了你问题的症结所在。快到了,我保证!

在您的示例中,您linkTo用于访问EventsNewRoute. 此外,您EventsNewRoute没有动态段,因此 Ember 确实调用了model钩子。并且controller.set("model", model);确实可以在controller.

问题与您使用renderTemplate. 当您在模板中使用renderor {{render}}helper 时,您实际上获得了与您正在使用的控制器不同的控制器。此控制器与您设置的控制器不同model,因此存在错误。

一种解决方法是在选项中传递控制器,这就是为什么要renderTemplate将此控制器作为参数。

renderTemplate: function(controller) {
  this.render("events-new", {
    outlet : "events-new", controller: controller
  });
}

这是一个更新的jsfiddle

最后说明:与此问题无关,您收到警告,

警告:直接父路由('application')没有渲染到主出口,默认的'into'选项('events')可能不是预期的

为此,您需要阅读此答案。警告,这是另一堵文字墙!:)

于 2013-07-24T13:50:54.727 回答