5

I have a model Category that has many Documents. When rendering an individual Category I want to list all the the child documents in a drag and drop sortable list. I also want double clicking on any individual document to allow inline editing for that document.

I got both parts working on there own, but can't seem to figure out how to merge them together.

For the sortable list I'm using a custom subclass of CollectionView to render the documents, and after inserting the element I call the html5sortable jquery plugin.

For the inline editing I set an itemController for each document being rendered. Inside the DocumentController I maintained application state of editing the document.

I'm looking for insight on how to combine the two approaches. What I think I need is a way to setup an itemController for each itemView in the CollectionView. I've put the relevant code below.

App.SortableView = Ember.CollectionView.extend({
    tagName: 'ul',
    itemViewClass: 'App.SortableItemView', 

    didInsertElement: function(){
        var view = this;
        Ember.run.next(function() {
        $(view.get('element')).sortable();
        });
    }
});

App.SortableItemView = Ember.View.extend({
    templateName: 'sortable-item',
    doubleClick: function() {
        //This should ideally send 'editDocument' to controller
    }
});

App.DocumentController = Ember.ObjectController.extend({
    isEditing:false,
    editDocument: function () {
        this.set('isEditing', true);
    },
    finishedEditing: function() {
        var model = this.get('model');
        model.get('store').commit();
        this.set('isEditing', false);
    }
});

<script type="text/x-handlebars" data-template-name="category">
    <h1>{{ name }}</h1>

    <h2>Documents</h2>
    <!-- This makes a sortable list -->
    {{view App.SortableView contentBinding="documents"}}

    <!-- This makes an editable list -->
    {{#each documents itemController="document"}}
        <!-- change markup dependent on isEditing being true or false -->
    {{/each}}

    <!-- How do I combine the two -->
</script> 

Thanks for any help. Really appreciate it.

raytiley
  • 684
  • 2
  • 7
  • 17

2 Answers2

2

The secret is to set itemController on your ArrayController instead of trying to set it on the view. Then, any views that bind to that ArrayController will get a controller back instead of whatever content is behind it.

To do that, you'll have to make an explicit DocumentsController:

App.DocumentsController = Ember.ArrayController.extend({
    needs: ['category'],
    contentBinding: 'controllers.category.documents',
    itemController: 'document'
});

and then in your categories:

App.CategoryController = Ember.ObjectController.extend({
    needs: ['documents']

Now, in your templates, bind to controllers.documents instead of documents.

Christopher Swasey
  • 10,392
  • 1
  • 31
  • 25
  • Thanks Christoper. That all makes sense but doesn't seem to be working for me. I implemented the DocumentsController like you said but if I log `controller` in the `sortable-item` template the controller is still the `category` controller. Here is the call to use the CollectionView: {{view App.SortableView contentBinding="controller.documents" }} Am I missing something? – raytiley Mar 23 '13 at 23:22
  • inside the individual view you want to reference `content`. What's happening is that the `DocumentsController` is transparently returning a `DocumentController` wrapped around every `document`. The `CollectionView` doesn't know nor care that this is happening: it still sets the value it gets back to `content`. If you'd like, you can bind `controller` to the `content` property on your itemView class. – Christopher Swasey Mar 24 '13 at 00:00
  • Thanks Christopher. I must stil be missing something obvious. In my template / view if I log out content its an instance of App.Document, not App.DocumentController, so for some reason the Documents Controller is still just giving the document, not the controller wrapped document. I'll try to make a fiddle of the code I have. Thanks for your time. – raytiley Mar 24 '13 at 00:31
  • Strange. If you put a fiddle or even just a gist of the relevant files together I can take a look. – Christopher Swasey Mar 24 '13 at 01:08
  • Yeah, something is strange. I did find a typo, i was using `controller.documents` not `controllers.documents`. Now the double click event gets to where it needs to, it calls the `editDocument` on the `DocumentController`. But the data in in the `sortable-item` template still isn't right. The data is coming from the `CategoryController` (I can tell because both category and document have a name.) https://gist.github.com/raytiley/5230046 Thanks again. Your really going above and beyond. I owe you a tasty beverage. – raytiley Mar 24 '13 at 01:29
  • Not sure what you mean by "both category and document have a name" – Christopher Swasey Mar 24 '13 at 01:48
  • Sorry, they both have a name property. So if I have a category like: {name: "Cat 1", documents: [{name: "doc 1}, {name: "doc 2"}]}.. when I use {{content.name}} in the sortable-item template I'm seeing two entires of "Cat 1" instead of "doc 1" and "doc 2" – raytiley Mar 24 '13 at 01:59
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/26808/discussion-between-christopher-swasey-and-raytiley) – Christopher Swasey Mar 24 '13 at 14:43
0

I think this is a bug in Ember, which is about to be resolved:

https://github.com/emberjs/ember.js/issues/4137

sandstrom
  • 14,554
  • 7
  • 65
  • 62