简体   繁体   中英

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!

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.

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM