Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Ember.js Models Loading Arrays of JavaScript objects

Nikolay Batrakov
Nikolay Batrakov
9,604 Points

Can't load an array from the application body

I'm building a simple web shop app based on the example from the course. When I don't declare a controller for my template I've got an error

Uncaught Error: Assertion Failed: An error occured while setting up template bindings. Please check for invalid markup or bindings within HTML comments. 

When I make just so:

Shop.CatalogController = Ember.Controller.extend({});

I've got

Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed Shop.CatalogController, but it should have been an ArrayController

Here is my html

<!DOCTYPE html>
<html>
  <head>
    <title>Shop</title>

    <link rel="stylesheet" href="css/bootstrap.css">
    <link rel="stylesheet" href="css/custom.css">

    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/handlebars-v1.3.0.js"></script>
    <script src="js/ember.js"></script>
    <script src="js/ember-handlebars-loader-0.0.1.js"></script>
    <script src="js/holder.js"></script>
    <script src="js/app.js"></script>

  </head>
  <body>
  <script type="text/x-handlebars" data-template-name="catalog">
    <div class="container-fluid">
      <div class="row">
       {{#each}}
          <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
          <img class="center-block product" data-src="{{url}}">
          <button type="button" class="center-block product btn btn-primary btn-lg">Купить</button> 
        </div>  
       {{/each}}
      </div>      
    </div>
  </script>
  </body>
</html>

and app.js

Shop = Ember.Application.create();

Shop.CatalogController = Ember.Controller.extend({});

Shop.Router.map(function() {
  this.resource('catalog', {path: '/'});
});

var products = [
  {
    id: '1',
    title: "Sky Box",
    descr: "This is the great sky box!",
    url: "holder.js/200x300/sky"
  },
  {
    id: '2',
    title: "Vine Box",
    descr: "This is the great vine box!",
    url: "holder.js/200x300/vine"    
  },
  {
    id: '3',
    title: "Lava Box",
    descr: "This is the great lava box!",
    url: "holder.js/200x300/lava"    
  },
  {
    id: '4',
    title: "Social Box",
    descr: "This is the great social box!",
    url: "holder.js/200x300/social"
  }
];

Shop.CatalogRoute = Ember.Route.extend({
  model: function() {
    return products;
  }
});

Pls help

2 Answers

Michael Kaiser-Nyman
STAFF
Michael Kaiser-Nyman
Treehouse Guest Teacher

Hi Nikolay! Try changing your controller to Shop.CatalogController = Ember.ArrayController.extend({});. The generic Ember.Controller.extend()doesn't present a model to your template.

You might wonder why it works when you don't define the controller at all. If you don't define a controller, Ember detects whether your model is an object, an array, or not defined, and automatically creates the appropriate controller for you.

Nikolay Batrakov
Nikolay Batrakov
9,604 Points

Hi Michael! Thank you, it works. And it now somehow works with generic controller either. :) Mystery! :) Well OK, it doesn't matter much, since it is certainly better to do everything through DS. I'm still wondering what was happened, but now I can't reproduce the error. :) Thank you for amazing intro for Ember.

Nikolay Batrakov
Nikolay Batrakov
9,604 Points

Just want to add an update. I rewrite the app in accordance with emberjs.com tutorial.

Shop.ApplicationAdapter = DS.FixtureAdapter.extend();

Shop.Catalog = DS.Model.extend({
  title: DS.attr('string'),
  descr: DS.attr('string'),
  url: DS.attr('string')
});

Shop.Catalog.FIXTURES = [
  {
    id: '1',
    title: "Orange Box",
    descr: "This is the great orange box!",
    url: "http://placehold.it/200x300/eb6c1b/696969"
  }, ... ];


Shop.CatalogRoute = Ember.Route.extend({
  model: function() {
    return this.store.find('catalog'); //here we find everything in DS.Store instance which is FIXTURE catalog
  }
});
  <script type="text/x-handlebars" data-template-name="catalog">
    <div class="container-fluid">
      <div class="row">
        {{#each catalog in model}}
          <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
            <img class="center-block product" {{bind-attr src="catalog.url"}}>
            <h4>{{catalog.title}}</h4>
            <p>{{catalog.descr}}</p>
            <button type="button" class="center-block product btn btn-primary btn-lg">Buy</button> 
          </div>
        {{/each}}  
      </div>      
    </div>
  </script>

and everything is working like a charm! You can see that it is necessary not to simply call {{title}} but to do like {{catalog.title}} and vice versa. It actually sounds reasonable for me.

holder.js doesn't work with ember. Fixed. :)

Please correct me if I was wrong, explaining the code. I'm going to move on to next chapter of the course, so maybe I'll be able to add something here in the future.

And I'm still curious why that doesn't work in line with course instructions.