Ember.js - CRUD 场景 - 从路由中指定视图 [英] Ember.js - CRUD scenarios - Specifying View from within a Route
问题描述
我之前问过一个问题,我想将驻留在控制器中的集合绑定到列表场景视图,但是,我添加了details 和 edit 我的结构的模板和视图产生了几个额外的子路线:
I've asked a question previously in which I wanted to bind a collection residing in the controller to the list scenario view, however, I've added details and edit templates and views to my structure producing a couple of extra sub-routes:
root.contacts.details ->/contacts/:contact_id
root.contacts.edit ->/contacts/:contact_id/edit
在我的 details
场景中,我首先开始调用 connectOutlets
如下
In my details
scenarios I first started calling the connectOutlets
as follows
[...]
connectOutlets: function (router, contact) {
router.get('contactController').set('contact', contact);
router.get('applicationController').connectOutlet('contacts');
},[...]
这会改变浏览器导航栏中的路线,但它会加载相同的视图,然后我将 .connectOutlet
更改为 contact 而不是 联系以下人员
This would change the route in the browser navigation bar, but it would load the same view, then I changed the .connectOutlet
to contact instead of contacts to the following
[...]
connectOutlets: function (router, contact) {
router.get('contactController').set('contact', contact);
router.get('applicationController').connectOutlet('contact');
},[...]
因此,我不得不创建一个新控制器,因为 Ember 找不到名为 contactController
的控制器,所以我最终得到了一个 contactController
和一个 contactsController
并且我认为我这样做打破了 MVC 模式,并创建了一个额外的类来维护同步可能出现的问题(编辑联系人时,我必须手动与集合中的contactsController
).此外,当我导航到 /#/contacts/2/edit
时,它会加载详细信息视图,因为我在 .connectOutlet('contact')
中使用了相同的名称.所以我所做的不可能是对的.我不想为每个场景创建控制器.我敢肯定这不是它的做法.
Because of this, I had to create a new controller as Ember couldn't find a controller named contactController
, so I ended up with a contactController
and a contactsController
and I think I'm breaking the MVC pattern doing this, as well as creating an extra class to maintain, possible problems with syncronization (when editing a contact I'd have to manually sync with the collection in the contactsController
). Also when I navigate to /#/contacts/2/edit
it loads the details view since I'm using the same name in .connectOutlet('contact')
. So what I'm doing can't be right. I don't want to create controller per scenario. I'm sure this is not how it's done.
我也尝试设置视图(在我的例子中是 App.EditContactView
)而不是 connectOutlets
中的资源名称,但我收到一个错误,说我可以通过一个名称或一个视图类,但不是两者",但我没有通过 viewClass
而是作为 connectOutlet
的参数传递.
I also tried setting the view (in my case App.EditContactView
) instead of the resource name in the connectOutlets
but I got an error saying I can pass "a name or a viewClass but not both" but I was not passing through viewClass
and rather as an argument of connectOutlet
.
我还尝试将视图或我的视图实例设置为路由本身,我要么破坏 JavaScript一个方法 CharAt".
I have also tried to set a view or an instance of my view to the route itself and I would either break my JavaScript or in some cases I'd get an error saying that "App.EditContactView does not have a method CharAt".
再说一次,我有点迷失了.我在 SO 和其他地方看到了其他问题,但我发现的问题要么使用 ember-routermanager
by Gordon Hempton(这看起来不错,但我现在只对使用内置感兴趣),Ember.StateManager
或不使用状态/路由全部.文档尚未对这些内容进行过多解释.
Then again, I got a little lost. I have seen other questions at SO and else where but the ones I've found were either using ember-routermanager
by Gordon Hempton (which seems good, but I'm interested in using built-in only right now), Ember.StateManager
or not using state/route at all. Documentation isn't explaining too much about these things yet.
问题:使用 Ember.Router
处理所有 CRUD 场景的理想方法是什么?我希望我的 contactsController
能够列出所有联系人、找到一个、编辑一个、添加一个和删除一个联系人.现在我有一个带有 findAll
的 contactsController
和一个带有 find
、edit
的 contactController
, remove
, add
因为命名问题.
Question: What would be the ideal approach to deal with all CRUD scenarios with Ember.Router
?
I want my contactsController
to be able to list all, find one, edit one, add one and delete one contact. Right now I have one contactsController
with findAll
and one contactController
with find
, edit
, remove
, add
because of naming problems.
我目前没有使用 ember-data,所以我会对没有引用 ember-data 的例子更感兴趣(我现在正在做没有任何插件的婴儿步骤).
I am currently not using ember-data so I would be more interested in examples without references to ember-data (I am doing the baby steps without any plug-in for now).
这是我的路由器的当前版本:
Here's the current version of my router:
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>
注意:如果有什么不清楚的,请在评论部分提问,我可以编辑更多细节
Note: If there's anything unclear, please ask in the comment section and I can edit this with more details
编辑:我已将此项目添加到 GitHub 即使它离我想作为学习样本公开的内容相去甚远.目标是在此基础上取得进展并在不久的将来创建一个 CRUD 模板.目前使用 MS Web API,但可能很快会添加 Rails 版本.
Edit: I've added this project to GitHub even tho it's nowhere near what I'd like to expose as a learning sample. The goal is to progress on top of this and create a CRUD template in a near future. Currently using MS Web API, but might add a Rails version soon.
推荐答案
这里发生了一些事情,我会尝试回答它们,但如果我错过了什么,请随时发表评论.你似乎在重新发明 Ember 已经为你做的很多事情.
There's a few things going on here, I'll try and answer them, but if I miss anything feel free to leave a comment. You seem to be reinventing a lot of stuff Ember already does for you.
首先,如果您想将视图传递给 connectOutlet
方法,您需要传入一个散列作为唯一的参数.
Firstly, if you want to pass a view to the connectOutlet
method you need to pass in a hash as the one and only argument.
router.get('applicationController').connectOutlet({
viewClass: App.EditContactView,
controller: router.get('contactsController'),
context: context
})
其次,拥有两个联系人控制器并不令人讨厌,事实上我会推荐它.从 ObjectController
继承的单一 ContactController
和从 ArrayController
继承的 ContactsController
,这意味着您可以轻松利用内置的内容代理.
Secondly, having two contact controllers is not frowned upon, in fact I'd recommend it. A singular ContactController
that inherits from ObjectController
and a ContactsController
that inherits from ArrayController
, this means you can easily take advantage of the content proxies built in.
第三,如果您将 find
和 findAll
类方法添加到您的模型中,您将更轻松.
Thirdly, if you add find
and findAll
class methods to your models you will make life much easier for yourself.
您不需要定义已定义的序列化/反序列化方法,默认情况下,Ember 将查找具有从路由推导出的名称的模型,因此 :contact_id 将自动查找 App.Contact.find(:contact_id).
You won't need to define the serialize/deserialize methods you have defined, by default Ember will look for a model with the name deduced from the route so :contact_id will automatically look for App.Contact.find(:contact_id).
您还可以将索引 connectOutlets 更改为:router.get('applicationController').connectOutlet('contacts', App.Contact.findAll())
You will also be able to change your index connectOutlets to: router.get('applicationController').connectOutlet('contacts', App.Contact.findAll())
另外一个提示,目前您的详细信息和编辑路线几乎完全相同.我会创建一个名为 company
的路由,然后在其中创建子详细信息并编辑视图.
One more tip, currently your details and edit routes are almost completely identical. I would create a single route called company
and then make child details and edit views inside of it.
这篇关于Ember.js - CRUD 场景 - 从路由中指定视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!