How to link to each nested routes in ember? - ember.js

I've got an ember app where my routing looks like this:
App.Router.map(function() {
this.resource('works', {path: '/works'}, function(){
this.route('work', {path:':work_id'})
});
});
I want to be able to link each of my work in my index template, for my naviguation. I tried this but it didn't work:
<script type="text/x-handlebars" data-template-name='application'>
<header id="header">
<nav id="main-nav" role="navigation">
<div class="item-container">
{{#link-to 'works' tagName='div' classNames="navItem work" }}
<p>Works</p>
{{/link-to}}
<ul>
{{#link-to 'work' works work}}{{work.title}}{{/link-to}}
</ul>
</div>
</nav>
</header>
<main id="main">
{{outlet}}
</main>
</script>
If you need more info just let me know.

Your index route definitions should look like this (assuming you are using Ember Data):
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('work');
}
});
Then in your index template go through {{each}} of the App.Work records and link to the works.work route:
<ul>
{{#each}}
<li>{{#link-to 'works.work' this}}{{title}}{{/link-to}}</li>
{{/each}}
</ul>

When linking to a route, you do resource.route
{{#link-to 'works.work' work}}{{work.title}}{{/link-to}}
In this case I'm assuming work is a property that is a model, if not, you'll need to show your router.

Related

Rendering model via nested templates in Ember

I'm building an app with multiple todo lists. The todo list used to correctly show todo model.
But I added function() to stack router to wrap todos router (so that it would correctly render todos template in stack template).
Then todos/index template (which is rendered through the outlet in todos) stopped displaying todo model.
This is my router structure:
Todos.Router.map(function() {
this.resource('stacks', {path: '/stacks'});
this.resource('stack', {path: '/stacks/:stack_id'}, function () {
this.resource('todos', { path: '/todos/:todos_id' }, function () {
// additional child routes will go here later
this.route('active');
this.route('completed');
this.route('new');
});
this.resource('todo', { path: 'todo/:todo_id' });
});
});
Stack template which renders Todo template:
<script type="text/x-handlebars" data-template-name="stack">
<h1>
<label {{action "editStack" on="doubleClick"}}>{{stackTitle}}</label>
{{input
value=stackTitle
action="createStack"}}
<div>{{model.stackTitle}}</div>
</h1>
{{render 'todos' todo}}
</div>
</script>
Then this todo template has an outlet for todo/index:
<script type="text/x-handlebars" data-template-name="todos">
<div class="container-fluid">
<section id="main">
{{outlet 'todos/index'}}
{{outlet modal}}
{{input type="checkbox" id="toggle-all" checked=allAreDone}}
</section>
</div>
</script>
And todo/index template:
<script type="text/x-handlebars" data-template-name="todos/index">
<ul id="todo-list">
<li {{bind-attr class="todo.isCompleted:completed todo.isEditing:editing"}}>
{{#each todo in model itemController="todo"}}
{{#if todo.isEditing}}
{{edit-todo class="edit" value=todo.title focus-out="acceptChanges"
insert-newline="acceptChanges"}}
{{else}}
{{input type="checkbox" checked=todo.isCompleted class="toggle"}}
{{outlet}}
<button {{action 'openModal' 'modal' model}}>
<label {{action "editTodo" on="doubleClick"}}>{{todo.title}}</label>
</button>
{{/if}}
</li>
{{/each}}
</ul>
</script>
Routers:
Todos.TodosRoute = Ember.Route.extend({
model: function() {
return this.store.find('todo');
},
});
Todos.TodosIndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('todos');
},
});
I've tried using {{partial}} helper in case that was a problem, but it didn't seem to change much.
Maybe I'm missing something in todos/index router that I need to call data through nested templates?
I appreciate your help!
There's a lot going on here but I think the root of your problem is with the way that you're using render in your templates/stack.
Since your routes/todos route is nested inside your routes/stack route, you're going to want to use an outlet inside your templates/stack if you want any of the templates for the nested routes to be rendered.
When you use render 'todos' todo, you're saying to render templates/todos with the todo property from the controllers/stack as the model. This isn't going to use your routes/todos or routes/todos-index to set the model.
What you probably want is for your templates/stack to have an {{outlet}} that either the routes/todos or routes/todo is rendered into when you visit either of those routes.

How make a ember modal with an id?

Hi i try to make an simple ember app that's get info form a json file. App is located here:http://www.autoroben.nl/m/. Problem is i need the ember view return back an id (from the li element) which i need for handlebars. so i can pop up car info with the same jsonfile as the car list.
// MODAL
App.OpenModal = Ember.View.extend({
click: function(evt) {
var id = $(".lijst li").attr('id');
alert(id)
$('#modal').addClass('active');
}
});
the template
<script type="text/x-handlebars" id="index">
<header class="bar bar-nav">
<h1 class="title">AUTOROBEN</h1>
</header>
<div class="content">
<ul class="table-view lijst">
{{#each}}
<li class="table-view-cell media" id="{{unbound ID}}">
{{#view App.OpenModal}}
<img src="/wp-content/uploads/{{unbound featured_image.attachment_meta.file}}" class="media-object pull-left" width="80">
{{title}}
<p>{{autoinfo.details.bouwjaar}} | {{autoinfo.details.kmstand}}</p>
{{/view}}
</li>
{{/each}}
</ul>
</div>
<div id="modal" class="modal">
<header class="bar bar-nav">
{{#view App.CloseModal}}
<a class="icon icon-close pull-right nostyle" href="#"></a>
{{/view}}
<h1 class="title">{{title}}</h1>
</header>
<div class="content">
<ul class="table-view">
<li class="table-view-divider">DETAILS</li>
<li class="table-view-cell">bouwjaar: {{autoinfo.details.bouwjaar}}</li>
<li class="table-view-cell">kmstand: {{autoinfo.details.kmstand}}</li>
</ul>
</div>
</div>
</script>
json file:
App.IndexRoute = Ember.Route.extend({
model: function() {
return Ember.$.getJSON('http://www.autoroben.nl/wp-json/posts/?type=autos');
}
});
Views in ember js by default get the parent context as its own context. In your case its the context of an single item in the each helper. You can access the ID from the view using the following code.
App.OpenModal = Ember.View.extend({
tagName: 'li',
classNames: ['table-view-cell', 'media'],
click: function(evt) {
alert(this.get('context.ID'));
$('#modal').addClass('active');
}
});
Here is a working bin.

Emberjs ,i dont know where take mistake

first,i can watch the data in blogs template.
<script type="text/x-handlebars" id="blogs">
<div>
<div>
{{#linkTo 'blogs' }}bogsCategory{{/linkTo}}
</div>
<ul>
{{#each controller}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</script>
then , build a new template "blogs/index" , to render into the blogs, but now, there nothing on my page.
<script type="text/x-handlebars" id="blogs/index">
<ul>
{{#each controller}}
<li>{{title}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" id="blogs">
<div>
<div>
{{#linkTo 'blogs' }}bogsCategory{{/linkTo}}
</div>
{{ outlet }}
</div>
</script>
i don't know where take mistake and how to do
Route:
App.Router.map(function(){
this.resource('blogs', { path: '/'});
});
App.BlogsIndexRoute=Em.Route.extend({
model: function(){
return App.Blog.find();
}
});
enter link description here
<----------------------------------------------------------------------------------------->
i want build a blog pag, the left is blogscategory, right is blog list, when i first into page, use 'blogs/index' to Initialization 'blogs', when click the blogscategory the blogs content will change by the category.
Have a look here at your working jsbin.
Basically I've changed BlogsIndexRoute to BlogsRoute and renamed the blogs template to application. Now it correctly renders the blogs/index template into the application template. I hope this is what you where trying to achieve.
Hope it helps.

Create a <li class="active"> around an active {{linkTo}}

What is the cleanest way to get <li class="active"> for the active page in the following Ember app?
index.html
<script type="text/x-handlebars">
<ul class="nav">
<li>{{#linkTo 'ping'}}Ping{{/linkTo}}</li>
<li>{{#linkTo 'pong'}}Pong{{/linkTo}}</li>
</ul>
</script>
app.js
App = Ember.Application.create()
App.Router.map(function() {
this.route("ping", { path: "/ping" });
this.route("pong", { path: "/pong" });
});
This workaround did it for me:
{{#linkTo 'menus.search' tagName='li' href=false}}
{{#linkTo 'menus.search'}}
<i class="icon-search"></i>
{{/linkTo}}
{{/linkTo}}
It creates an li element containing an anchor element. And both will be updated with the "active" class when the route is active.
replace in your template the li tags like so:
index.html
<script type="text/x-handlebars">
<ul class="nav">
{{#linkTo 'ping' tagName="li"}}Ping{{/linkTo}}
{{#linkTo 'pong' tagName="li"}}Pong{{/linkTo}}
</ul>
</script>
the {{linkTo}} with the tagName specified will apply a css class name of 'active' automatically when the application's current route matches the supplied route name.
example, when your app url is at /#/ping the resulting markup would be something like:
...
<li class="active">Ping</li>
...
Or you create a custom view
App.ItemView = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews.firstObject.active');
}.property()
});
and then use it like so
<script type="text/x-handlebars">
<ul class="nav">
{{#view App.ItemView}}
{{#linkTo 'ping'}}Ping{{/linkTo}}
{{/view}}
{{#view App.ItemView}}
{{#linkTo 'pong'}}Pong{{/linkTo}}
{{/view}}
</ul>
</script>
some css to see it actually working
li a {
color: #000;
}
li a.active {
color: #f00;
}
hope it helps
Just nest the {{link-to}} with a tagName on the outer one. This will set an active class on both the outer <li> and the inner <a> tag.
{{#link-to "ping" tagName="li"}}
{{#link-to "ping"}}ping{{/link-to}}
{{/link-to}}
{{#link-to "pong" tagName="li"}}
{{#link-to "pong"}}pong{{/link-to}}
{{/link-to}}

handlebars view not refreshing when {{#if}} {{else}} condition changes

(edit: simplified things a bit below)
I have a handlebars template with an {{#if etc}} conditional, and when I change the associated data the view updates the first time, but then does not continue to update on subsequent changes. I am toggling a boolean that is in the condition, and I know the toggle is running and switching the property because I can watch it do so on the console, but the actual view, a I said, only refreshes once. In my html file this looks like this:
<script type="text/x-handlebars" data-template-name="application">
<body>
<div class="row">
{{#if App.Nav.show}}
{{outlet nav}}
{{/if}}
<div class="span10">
<h1>Hello</h1>
{{outlet}}
</div>
</div>
</body>
</script>
and a bit further on, to toggle:
<script type="text/x-handlebars" data-template-name="people">
<a {{action toggleMenu}}> toggle </a>
</script>
and in the javascript:
App.NavController = Ember.Controller.extend();
App.NavView = Ember.View.extend({
templateName: 'nav'
});
App.Nav = Ember.Object.create({
show: true
});
and finally the relevant bits of the router:
App.Router = Ember.Router.extend({
enableLogging: true,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
showPerson: Ember.Route.transitionTo('aName'),
toggleMenu: function(){
console.log('Changing the toggle!');
App.Nav.toggleShow();
},
connectOutlets: function(router){
router.get('applicationController').connectOutlet('nav', 'nav');
router.get('applicationController').connectOutlet('allPeople', unrelated_function())
}
})
})
});
I would say to put your if into your view. Something like this:
<script type="text/x-handlebars" data-template-name="people">
<a {{action toggleMenu}}> toggle </a>
{{#if App.Nav.show}}
<div>navigation</div>
{{/if}}
<div class="span10">
<h1>Hello {{name}}</h1>
</div>
</script>
Then your application view should look something like this:
<script type="text/x-handlebars" data-template-name="application">
<body>
<div class="row">{{outlet}}</div>
</body>
</script>
Let me know if you tried it and it worked.
I did not use connectOutlet to display the view, let me know if there is some purpose behind using connectOutlet method, Meanwhile here is my implementation of toggling the view visibility