Currently selected model conditional in a loop w/ link-to


#1

So I’ve been researching this topic for a couple of hours, trying to find a good (and preferably, proper) solution to determining if a model is currently selected after either a page reload or a transition from a link-to helper.

Currently, I have code that looks like this:

{{#each list as |item| }}
	{{#link-to 'post' item.id}}
		{{#md-list-item class="md-3-line"}}
			<div class="md-list-item-text">
				<h5>{{item.title}}</h5>
				<h6>{{item.author}}</h6>
				{{item.id}}
			</div>
			<md-divider></md-divider>
		{{/md-list-item}}
	{{/link-to}}
{{/each}}

What I would like to accomplish is something that looks like this:

{{#each list as |item| }}
	{{#if ...item is currently selected... }}
		{{#md-list-item class="md-3-line"}}
			...some special representation of a selected post...
		{{/md-list-item}}
	{{else}}
		{{#link-to 'post' item.id}}
			{{#md-list-item class="md-3-line"}}
				<div class="md-list-item-text">
					<h5>{{item.title}}</h5>
					<h6>{{item.author}}</h6>
					{{item.id}}
				</div>
				<md-divider></md-divider>
			{{/md-list-item}}
		{{/link-to}}
	{{/if}}
{{/each}}

I’m currently on Ember 1.13. I’d prefer a solution that isn’t very ‘hacky’ and conforms to the Ember philosophy (but otherwise…I could use the help anyway). Currently, the ‘list’ variable is passed to a component which holds the {{#each}} block above. I have also tried replacing the ‘link-to’ helpers with actions, but had a lot of difficulty maintaining the currently selected item (especially if I loaded the route directly) and having the component manage transitions to the route. If possible, I would also prefer a future proof solution.

I hope someone can help me out and I thank you for your time!


#2

Could you just pass the current post item id to the component as well? And then just compare the id to the one the loop is iterating over.


#3

The post is selected within the component using link-to, so the component is never aware of the item id :confused:


#4

But the link-to causes a transition to a context that is aware of the current ID. The component is then rendered again within the template of that context. Just as you pass the list from the context to the component, you can do the same for the current ID.


#5

So I have a ‘posts’ and ‘post’ templates and routes. The posts template contains a component on the left and an outlet on the right. In that template, I pass the model into a variable called ‘list’. Inside that component, I have my link-to’s and such. And then when I click on one of them, it loads the ‘post’ route and template in place of the outlet in the ‘posts’ template. So you’re saying I am still able to pass that current post id and access it within the parent ‘posts’ template and route? Could you possibly give an example or some sample code as to how I would actually accomplish this?


#6

I ended up down the rabbit hole on this but it was really bugging me and I couldn’t let it go. What I came up with is something like:

posts route:

actions: {
  setCurrentId: function(currentId) {
    console.log("currentId: " + currentId);
    this.controllerFor("posts").set("currentId", currentId);
  }
}

post route:

setupController: function(controller, model){
  this._super(controller, model);
  if (model) {
    this.controllerFor("posts").send("setCurrentId", model.id);
  }
}

However, you’ll still need to create a template helper as conditionals are limited. See this thread.

I don’t know if this is the best way to handle it but it’s the only thing that I’ve been able to make work.

EDIT: little change to add controllerFor() EDIT 2: see this truth helpers package