How can I set a link to route with a dynamic segment
Asked Answered
C

1

7

How can I set a link to route with a dynamic segment. According to guide I start with this

window.App = Ember.Application.create()
App.Router.map ->
  @resource 'products'
  @resource 'product', path: '/product/:product_id'

in my template:

{{#linkTo "product.1"}}products{{/linkTo}}

Unfortunately this gives me the follwing error:

Uncaught Error: assertion failed: The attempt to linkTo route 'product.1' failed. 
The router did not find 'product.1' in its possible routes: 'products', 'product', 'index' 
Craigcraighead answered 30/4, 2013 at 22:8 Comment(0)
G
11

{{linkTo}} expects the route defined in the Router.map, so in according to your mapping it should be simply product.

As for the dynamic segment, you also have to pass an object which will be serialized in the ProductRoute. The serialization in almost all scenarios occur without the developer having to do anything since Ember relies on conventions. In rare cases, one must implement serialize a little differently, but for most cases you don't have to touch it.

If you're using {{linkTo}} inside an {{each}} loop you can do it like this:

{{#each product in controller}}
    {{#linkTo product product}}Details{{/linkTo}}
{{/each}}

or

{{#each controller}}
    {{#linkTo product this}}Details{{/linkTo}}
{{/each}}

Where the first argument is the route name and the second is your model object. In the first code the object has been also named as product, while in the second it's simply being passed as this, which is the product of the iteration.

If you have an unusual scenario where you have to link to a dynamic route while not using the {{each}} loop, you have to expose the object in the controller (preferred) or view. Then you'd have to do something similar to the following:

App.SomeController = Em.Controller.extend
  product: null

App.SomeRoute = Em.Route.extend
  ### 
  controller is actually `SomeController` here
  model is not being used, and is null, while the actual model being
  supplied to the controller is `product`, retrieved from store
  ###
  setupController: (controller, model) ->
    product = App.Product.find 1
    controller.set 'product', product
    return

While your template would be similar to this:

{{#linkTo product controller.product}}Product{{/linkTo}}

How does the route know the id?

Conventions. The route will serialize the object you pass, and expose an object with a single property, which has the name of the model for that route, followed be "_id", which in this case would be product_id, so when you click that link, the app activates the ProductRoute, runs the serialize method creating that id property, which will subsequently be used as the argument of the model hook. That's where you call find passing params.product_id as argument. Then the model returns a promise of that model which will be used by the setupController, exposing the object to the view layer as controller.content or simply controller.

Galengalena answered 30/4, 2013 at 23:30 Comment(1)
In the #each-loop i had to quote product: {{#linkTo 'product' this}}Details{{/linkTo}}.Mordancy

© 2022 - 2024 — McMap. All rights reserved.