2012-07-07 15 views
7

我问了一个问题以前,我想bind a collection residing in the controller to the list scenario view,但是,我已经添加细节编辑模板和意见,我的生产结构一对额外的子路线:Ember.js - CRUD场景 - 从路径中指定查看

root.contacts.details -> /contacts/:contact_id
root.contacts.edit -> /contacts/:contact_id/edit

在我details情景我第一次开始调用connectOutlets如下

[...] 
connectOutlets: function (router, contact) { 
    router.get('contactController').set('contact', contact); 
    router.get('applicationController').connectOutlet('contacts'); 
},[...] 

这会改变在浏览器导航栏的路线,但它会加载相同的视图,然后我改变了.connectOutlet接触代替触点以下

[...] 
connectOutlets: function (router, contact) { 
    router.get('contactController').set('contact', contact); 
    router.get('applicationController').connectOutlet('contact'); 
},[...] 

正因为如此,我不得不创建一个新的控制器,因为Ember无法找到名为contactController的控制器,所以我最终得到了contactControllercontactsController,我认为我打破了这样做的MVC模式,以及创建一个额外的类来维护,同步可能出现的问题(编辑联系人时,我必须手动与contactsController中的集合同步)。另外,当我导航到/#/contacts/2/edit时,它会加载详细信息视图,因为我在.connectOutlet('contact')中使用了相同的名称。所以我正在做的事情是不对的。我不想为每个场景创建控制器。我相信这不是如何完成的。

我也试过在connectOutlets设置视图(在我的情况App.EditContactView),而不是资源的名字,但我得到了一个错误,说我可以通过“名称或viewClass类,但不能同时”但我不及格通过viewClass,而不是作为connectOutlet的论点。

我也试图设置一个视图或我的视图的实例路线本身,我会打破我的JavaScript或在某些情况下,我会得到一个错误,说“App.EditContactView没有方法CharAt“。

然后我又有点迷路了。我在SO上看到过其他问题,除此之外,我发现使用Gordon Hempton的ember-routermanager(这看起来不错,但我只对现在使用内置感兴趣),Ember.StateManager或者没有使用state /在所有路线。文档没有太多解释这些事情。

问题:用Ember.Router来处理所有CRUD场景的理想方法是什么? 我希望我的contactsController能够列出全部,找到一个,编辑一个,添加一个并删除一个联系人。现在我有一个contactsControllerfindAll和一个contactControllerfind,edit,remove,add由于命名问题。

我目前没有使用烬数据,所以我会更感兴趣的例子没有引用烬数据(我现在做没有任何插件的婴儿步骤)。

这里是我的路由器的当前版本:

JS

App.Router = Ember.Router.extend({ 
    enableLogging: true, 
    location: 'hash', 

    root: Ember.Route.extend({ 
     // EVENTS 
     gotoHome: Ember.Route.transitionTo('home'), 
     gotoContacts: Ember.Route.transitionTo('contacts.index'), 

     // STATES 
     home: Ember.Route.extend({ 
      route: '/', 
      connectOutlets: function (router, context) { 
       router.get('applicationController').connectOutlet('home'); 
      } 
     }), 
     contacts: Ember.Route.extend({ 
      route: '/contacts', 
      index: Ember.Route.extend({ 
       route: '/', 
       contactDetails: function (router, context) { 
        var contact = context.context; 
        router.transitionTo('details', contact); 
       }, 
       contactEdit: function (router, context) { 
        var contact = context.context; 
        router.transitionTo('edit', contact); 
       }, 
       connectOutlets: function (router, context) { 
        router.get('contactsController').findAll(); 
        router.get('applicationController').connectOutlet('contacts', router.get('contactsController').content); 
       } 
      }), 
      details: Ember.Route.extend({ 
       route: '/:contact_id', 
       view: App.ContactView, 
       connectOutlets: function (router, contact) { 
        router.get('contactController').set('contact', contact); 
        router.get('applicationController').connectOutlet('contact'); 
       }, 
       serialize: function (router, contact) { 
        return { "contact_id": contact.get('id') } 
       }, 
       deserialize: function (router, params) { 
        return router.get('contactController').find(params["contact_id"]); 
       } 
      }), 
      edit: Ember.Route.extend({ 
       route: '/:contact_id/edit', 
       viewClass: App.EditContactView, 
       connectOutlets: function (router, contact) { 
        router.get('contactController').set('contact', contact); 
        router.get('applicationController').connectOutlet('contact'); 
       }, 
       serialize: function (router, contact) { 
        return { "contact_id": contact.get('id') } 
       }, 
       deserialize: function (router, params) { 
        return router.get('contactController').find(params["contact_id"]); 
       } 
      }) 
     }) 
    }) 
}); 
App.initialize(); 

相关模板

<script type="text/x-handlebars" data-template-name="contact-details"> 
    {{#if controller.isLoaded}} 
     <img {{bindAttr src="contact.imageUrl" alt="contact.fullName" title="contact.fullName"}} width="210" height="240" /><br /> 
     <strong>{{contact.fullName}}</strong><br /> 
     <strong>{{contact.alias}}</strong> 
    {{else}} 
     <img src="images/l.gif" alt="" /> Loading... 
    {{/if}} 
</script> 

<script type="text/x-handlebars" data-template-name="contact-edit"> 
    <strong>Edit contact</strong><br /> 
    First Name: <input type="text" id="txtFirstName" {{bindAttr value="contact.firstName"}}<br /> 
    Lasst Name: <input type="text" id="txtLastName" {{bindAttr value="contact.lastName"}}<br /> 
    Email: <input type="text" id="txtEmail" {{bindAttr value="contact.email"}}<br /> 
</script> 

<script type="text/x-handlebars" data-template-name="contact-table-row"> 
    <tr> 
     <td> 
      <img {{bindAttr src="contact.imageUrl" alt="contact.fullName" title="contact.fullName"}} width="50" height="50" /><br />{{contact.fullName}} 
     </td> 
     <td> 
      Twitter: {{#if contact.twitter}}<a {{bindAttr href="contact.twitter"}} target='_blank'>Follow on Twitter</a>{{else}}-{{/if}}<br /> 
     </td> 
     <td> 
      <a href="#" {{action contactDetails context="contact"}}>Details</a> | 
      <a href="#" {{action contactEdit context="contact"}}>Edit</a> 
     </td> 
    </tr> 
</script> 

注意:如果有什么不清楚的地方,请咨询中评论部分,我可以e DIT这更多的细节

编辑:我已经添加了这个项目GitHub即使寿它远不及希望我揭露作为一个学习的样本。目标是在此基础上取得进展,并在不久的将来创建一个CRUD模板。目前使用MS Web API,但很快可能会添加Rails版本。

+0

我得到一个404链接到Github页面。最近这个变化了吗? – mkelley33 2012-09-24 05:31:22

+1

是的..我改变了项目名称。这里是[新链接](https://github.com/MilkyWayJoe/hello-ember-router) – MilkyWayJoe 2012-09-24 13:16:28

+0

谢谢@MilkyWayJoe – mkelley33 2012-09-24 22:46:50

回答

9

这里有几件事情,我会尽力回答,但如果我错过任何事情,请随时发表评论。你似乎正在重塑Ember已经为你做的很多东西。

首先,如果你想传递一个视图到connectOutlet方法,你需要传入一个散列作为唯一的参数。

router.get('applicationController').connectOutlet({ 
    viewClass: App.EditContactView, 
    controller: router.get('contactsController'), 
    context: context 
}) 

其次,有两个接触控制器不皱眉,实际上我会推荐它。单数ContactControllerObjectControllerContactsControllerArrayController继承继承,这意味着你可以轻松地建在内容代理的优势。

第三,如果添加findfindAll类的方法,以你的模型将使生活对自己来说更容易。

  • 你不会需要定义你所定义的序列化/反序列化方法,默认情况下灰烬将寻找从路线,以便推断名称型号:CONTACT_ID会自动寻找App.Contact.find (:CONTACT_ID)。

  • 你也可以改变你的指数connectOutlets到:router.get('applicationController').connectOutlet('contacts', App.Contact.findAll())

一个提示,目前您的详细资料和编辑路线几乎完全一致。我会创建一个名为company的路线,然后在其中创建子细节并编辑视图。

+0

感谢您的回答,我会一点一滴地对此进行讨论,但在我尝试之前,我想知道更多关于控制器的信息,您如何去同步数据?假设你在控制器中有一个从ObjectController继承的创建方法,你会手动将一个由ObjectController实例创建的记录拷贝到ArrayController集合中吗?也许我太严格了,但我不认为我喜欢为同一资源类型设置多个控制器,这是Ember的惯例吗?(我有一个不同的应用程序,使用StateManager和这个资源的单个控制器) – MilkyWayJoe 2012-07-08 12:29:33

+0

如果我在'connectOutlet'中用这段代码调用我的'edit'路径,它会抛出'Uncaught Error:断言失败:您必须提供一个名称或视图类connectOutlets,但不是两个' – MilkyWayJoe 2012-07-08 12:34:58

+0

我已经'viewClassName:App.EditContactView'更改为'viewClass:App.EditContactView'。我不再收到以前的错误消息,但我的路线和视图将不会加载。网址保持不变,视图保持不变,只是现在没有数据。 – MilkyWayJoe 2012-07-08 12:51:26