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
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');
},[...]
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');
},[...]
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.
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
.
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".
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.
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.
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();
Relevant templates
<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
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.