Retrieving info from Express with `each` - Question


#1

Bonjour,

First thing’s first, this is a poorly phrased question, I’m sorry about that.

I’m using (MongoDB, Express, Ember, and Node) to build a reference engine. Pretty much everything is going smoothly until I need to read info from the database.

I have an express route (/charlist) that has:

ul
	each char, i in charlist
		li
			p #{char.name}

It’s in Jade, but as I understand it, it’s an each statement looking for char.name in char. I took this setup directly from this tutorial, which doesn’t explain what “char” (or in the tuts’ case, ‘user’) actually refers to. But, on the Express route, it works just fine.

Writing the same statement in Ember, however, doesn’t work.

    <ul>
    {{#each char in charlist}}
        <li>{{name}}</li>
    {{else}}
        Sorry, nothing here.
    {{/each}}
</ul>

With that, I get the else message. Replacing {{name}} with {{char.name}} does the same thing. Copying it directly, and using
<li>#{char.name}</li>
throws a “Cannot read property ‘name’ of undefined” error.

I’m not exactly sure what I need to do to get Express to hand off the data to Ember.

This is the Express router that gets the character information (ignore the weird spacing caused by the code indent here):

/* GET Character page. */
router.get('/charlist', function(req, res) {
var db = req.db;
var collection = db.get('charcollection');
collection.find({},{},function(e,docs){
	res.render('charlist', {
		"charlist" : docs
	    });
	});
});

Here’s the handlebars template (in .jade):

  script(type="text/x-handlebars" id='test').
<h1>Character list</h1>
<ul>
    {{#each char in charlist}}
        <li>#{char.name}</li>
    {{else}}
        Sorry, nothing here.
    {{/each}}
</ul>

A friend told me to, basically, wrap the whole Express bit in a variable and call it from Ember, but neither of us know if that would actually help. Obviously, I have a database with content, and there is a name field, the Express route is functional, just need to figure out how to get it to work with Ember.

Any advice on getting this to work would be greatly valued, thanks!


#2

It looks like you’re mixing Jade template and Handlebars template together. #{char.name} is not the syntax used by Handlebars to render the each.

Try {{char.name}} instead.


#3

I’ve tried that variation (and several others).

    <ul>
    {{#each char in charlist}}
        <li>{{char.name}}</li>
    {{else}}
        Sorry, nothing here.
    {{/each}}
</ul>

Returns the else statement.

Other variations (such as {{name}} or {{char.title}} (title being another part of the db), return the else statement.


#4

That just shows charlist is empty. How did you loaded the data from backend? Can you confirm that it’s indeed loaded?

Here are a few tools to help you diagnose the problem:

Ember’s template lookup charlist from the template’s controller. You can use Ember inspector to inspect whether the controller did get the charlist loaded.


#5

The data is loaded via Express, as I said in the opening post.

/* GET Character page. */
router.get('/charlist', function(req, res) {
var db = req.db;
var collection = db.get('charcollection');
collection.find({},{},function(e,docs){
	res.render('charlist', {
		"charlist" : docs
	});
});
});

The collection isn’t empty, it has four items in it, and the Express route works fine (meaning, I know it’s getting things from the database - I don’t know how to tell Express to give those things to Ember). I’m asking how to get Express to give the data to Ember, I guess that wasn’t clear in my post.


#6

Ah, that part is actually pretty open. All you need to do is get jQuery from Ember.$ and ajax away!

You need to convert whatever native array into an Ember array via Ember.A. Then stick it to an Controller matching the same name your template. In this case, TestController.


#7

I’m sorry for asking, but I’m an extremely dense person and I’m generally a visible learner. I can’t find Ember.A in the Guides, I assume you’re talking about Ember.Array? Could you point me to an example of running jQuery in Ember? Not for this, just so I can figure out how it fits together.


#8

Here’s the doc for Ember.A: http://emberjs.com/api/#method_A

There are no concrete example on how to run jQuery on Ember. The jQuery namespace is nested under Ember so you get get it from Ember.$. The only concrete thing is that you need to attach an Ember.NativeArray to the controller for the view to render it. That’s why I said it’s pretty open for you to decide what to do.

For starter, you can just go ahead and attach something on the controller without ajax.

App.TestController = Ember.Controller.extend({
  charlist: Ember.A([
    {
      name: 'hello world'
    }
  ])
});

Next step, you need to set charlist from somewhere. This can be on the route or controller as both offers way to retrieve the specific controller via #controlleFor. Take note that an Ember route and Express route are separate things. Although the default implementation for Ember.Route#model (here) tries to load it from matching backend route. This is something you can override to have your own behavior.

Models are usually loaded from route as shown in the guide. But the default behavior for route is to render the model to the template matching the same name as the route. This behavior, again, is override-able via Ember.Route#renderTemplate hook. See the default implementation of this hook. It just calls Ember.Route#render. Take a look at the doc for Ember.Route#render and you’ll see you can use it to render any template into any template with any combination of view, controller, or model.

App.TestRoute = Ember.Route.extend({
  model: function() {
    // ajax returns an non-standard promise.
    // see https://github.com/instructure/ic-ajax
    // for a good wrapper for it.
    return Ember.RSVP.cast(Ember.$.ajax( ... ))
  },
  renderTemplate: function(model) {
    // model is the resolved promise from above
    this.render('test', {
      into: ??,
      model: model
    });
  }
});

#9

Ah, cool, thanks!

I was able to test things and get it to read from there, now I just need to get an ajax bit into Ember.A to load it from the collection. I can’t actually get ic-ajax to work, but I posted that issue over there.

Thanks!