0
votes

I want App.IndexRowController to be the controller for the three row views. Instead Ember sets them to plain Objects. I believe I'm properly setting itemController in the DataIndexController. I a version of this code without the nested route working as expected. Do I need to do something special when working with nested routes/needs?

JSBin: http://jsbin.com/sazafi/edit?html,css,js,output

To see the behavior go to #/data/index. Notice there are three li elements but no corresponding text (from getName). The getName controller property isn't accessible from the row template. Ember docs say that setting the itemController in the ArrayController should make that controller available to the template specified in itemViewClass. Take a look at the Ember Inspector and see that the controller for the three views is an Ember.Object, not App.IndexRowController.

JavaScript:

App = Ember.Application.create();

App.Router.map(function() {
    this.resource("data", function() {
        this.route("index")
    });
});

App.DataIndexRoute = Ember.Route.extend({
    model: function() {
        return(
            [
                Ember.Object.create({name: 'row 1'}),
                Ember.Object.create({name: 'row 2'}),
                Ember.Object.create({name: 'row 3'})
            ]);
    }
});

App.DataController = Ember.ArrayController.extend({
    filter: ''
});

App.DataIndexController = Ember.ArrayController.extend({
    needs: ['data'],
    itemController: 'indexRow',
    filter: Ember.computed.alias("controllers.data.filter"),

    filteredContent: function(){
        var filter = this.get('filter');
        var list = this.get('arrangedContent');

        return list.filter(function(item) {                
            return item.get('name').match(filter);
        });
    }.property('content', 'filter')
});

App.IndexRowController = Ember.ObjectController.extend({
    // This method isn't accessible from the row template
    getName: function() {
        return(this.get('content').get('name'));
    }.property()
});

App.DataIndexView = Ember.CollectionView.extend({
    tagName: 'ul',
    content: function(){
        return this.get('controller.filteredContent')
    }.property('controller.filteredContent'),

    itemViewClass: Ember.View.extend({
        controllerBinding: 'content',
        templateName: 'row'
    })
});

HTML:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Collection View</title>
<script src="http://code.jquery.com/jquery-2.0.2.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.1.2.js">  </script>
<script src="http://builds.emberjs.com/release/ember.js"></script>
<script src="app.js"></script>
</head>

<body>
<script type="text/x-handlebars" data-template-name="application">
<h1>CollectionView With Item View</h1>
{{outlet}}
</script>


<script type="text/x-handlebars" data-template-name="data">
{{input type="text" placeholder='row 1' value=filter}}
{{outlet}}
</script>

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

</body>
</html>

EDIT: I have a working example of how to set the controller in a child view of a Ember.ContainerView and how to filter the contents here: https://github.com/mkolenda/ember-listview-with-filtering. ListView is a descendent of ContainerView.

1

1 Answers

0
votes

Simple solution is to use an {{each}} instead of a CollectionView.

This is a well-known "feature", aka design bug, in the Ember design for array controllers, item controllers, and collection views. It shouldn't be too hard to find references on the web about the problem and some suggested hacks/workarounds. You might start with https://github.com/emberjs/ember.js/issues/4137 or https://github.com/emberjs/ember.js/issues/5267.