Ember, Ember-data, and jquery-ui.dialog, "Oh my!"



任务:

在灯箱中打开表单以创建新的";事件";;打开的表单应该是可添加书签的。

路障:

  1. 有一些使用{{action}}标记打开灯箱的示例,但找不到在自己的路径中打开的灯箱
  2. 有很多使用旧版本ember.js的例子
  3. 没有太多与ember数据和REST相关的文档(我知道,我知道……它还没有"生产就绪")

问题是:

表单中的字段没有与支持模型绑定;空";正在被发布到我的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插件会导致操作不可用(lightbox"example")
  4. Ember中的可靠视图(另一个灯箱"示例",但没有灯箱打开的路线)

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

Ember使URL成为其约定中不可或缺的一部分。这意味着应用程序的state由它所在的路由表示。但有一些细微的差别,我将在下面澄清。

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

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

比如说,在/posts点击列表中的一篇文章,就会进入/posts/1

在这种情况下,用户可以通过两种方式在/posts/1上查看帖子。

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

在这两种情况下,/posts/1PostRoute将需要对应于Post id 1的模型。

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

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

您的post模板将获得模型,并可以使用其属性进行渲染。

现在考虑第二种情况。点击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钩子。而CCD_ 27的作用与其说是在CCD_ 28上设置模型。

问题与您使用renderTemplate有关。当您在模板中使用render{{render}}辅助对象时,您实际上得到了与正在使用的控制器不同的控制器。此控制器与您设置model的控制器不同,因此出现错误。

解决方法是在选项中传递控制器,这就是renderTemplate将此控制器作为参数的原因。

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

这是一个更新的jsfiddle。

最后一点:与这个问题无关,你得到了警告,

警告:直接父路由("应用程序")未呈现到主出口,并且可能不需要默认的"进入"选项("事件")

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

最新更新