Edy Bourne
Edy Bourne

Reputation: 6207

Ember's link-to helper not linking to correct URL when using {{#each x in model}} syntax?

I have a router that looks like this:

App.Router.map(function() {
    this.resource("manage", function() {
        this.resource('services' , function() {
            this.route("new");
            this.route("edit", { path: '/edit/:service_id' } );
        });
    });
});

The services.index route loads the model from the server:

App.ServicesIndexRoute = Ember.Route.extend({
    model: function() {  
        return this.store.find('service');
    }
});

Which returns:

{
  "services" : [ {
    "id" : 1,
    "serviceId" : "service1",
    "name" : "Service A"
  }, {
    "id" : 2,
    "serviceId" : "service2",
    "name" : "Service B"
  } ]
}

Then inside the services index template I'm listing the services returned by the server with a {{each}} loop, like so:

<tbody>
    {{#each service in model}}
        <tr class="odd">
            <td>{{service.serviceId}}</td>
            <td>{{service.name}}</td>
            <td>{{#link-to 'services.edit' this}}Edit{{/link-to}} - <a href="#" {{action 'deleteService' this}}>Delete</a></td>
        </tr><!-- Table Row -->
    {{/each}}
</tbody>

The issue is that when the template renders, it replaces the path segment with "undefined":

<a id="ember502" class="ember-view" href="#/manage/services/edit/undefined">Edit</a>

...and the deleteService method gets passed an object which has a property with two services, instead of the service instance in question.

Then I tried:

<tbody>
    {{#each}}
        <tr class="odd">
            <td>{{serviceId}}</td>
            <td>{{name}}</td>
            <td>{{#link-to 'services.edit' this}}Edit{{/link-to}} - <a href="#" {{action 'deleteService' this}}>Delete</a></td>
        </tr><!-- Table Row -->
    {{/each}}
</tbody>

and it worked!

I'm trying to understand what happened in the previous attempt. I'm trying to use the {{@each x in model}} syntax and would like to understand why the this didn't work with that setup...

What did I do wrong?

Thanks!

Upvotes: 0

Views: 73

Answers (2)

prabhash
prabhash

Reputation: 56

The thing is, {{#each x in model}} is used to maintain the scope, meaning you will be able to access anything on the model from within the loop, so something like this works with {{#each x in model}}

{{#each service in model}}
  service.id
  service.name
  this.aVariableOnModel
{{/each}}

So essentially, this still remains bounded to the model, and this is very useful and hence its always encouraged to use {{#each x in model}} syntax..

So, in your case, that would mean..if you just do this.

<td>{{#link-to 'services.edit' service}}Edit{{/link-to}} - <a href="#" {{action 'deleteService' this}}>Delete</a></td>

It will work.

Cheers!

Upvotes: 1

Matthew Blancarte
Matthew Blancarte

Reputation: 8301

If you change this to service or whatever you named the iterated items, it should work.

{{#link-to 'services.edit' service}}Edit{{/link-to}}

Just like JS, if you override this with some particular context (think call, apply, bind, etc.) you will need account for the scope change.

Ember Handlebars mimics that behavior within template loops. If you specify a particular name for the iterated object, this will become undefined as the context was given a name.

Upvotes: 1

Related Questions