EmberJS linkTo nested resource is re-rendering the parent view - javascript

I'm trying to create a simple interface with a list of links on the left, retrieved from an AJAX call, that, when clicked, open in an {{outlet}} to the right with some data, retrieved as well from another AJAX call from that link. So these are my routes:
App.Router.map(function() {
this.resource('about');
this.resource('subreddit', { path: 'subreddit/:subreddit_name' }, function() {
this.resource('comments', { path: 'comments/:id' })
});
});
So I have a dynamic list of links, based on :subreddit_name with the following structure:
subreddit/:subreddit_name/comments/:id
To create the links I have the following codeblock:
<script type="text/x-handlebars" id="subreddit">
<div>
{{#each item in model}}
{{#linkTo 'comments' item.subreddit item.id classNames="list-group-item"}}
<img class="media-object" {{bindAttr src="item.thumbnail"}} class="img-rounded">
{{item.author}}
{{/linkTo}}
{{/each}}
</div>
<div>{{outlet}}</div>
</script>
The link is properly corrected, but, after I've inserted the :subreddit_name dynamic route to the Router, when I click the link it re-renders the whole template, instead of re-rendering only the template for the comments:
<script type="text/x-handlebars" id="comments">
{{#each item in model}}
<div class="panel panel-info mypanel">
<div class="panel-heading">{{item.author}}</div>
<div class="panel-body">
<p>{{{item.body}}}</p>
</div>
</div>
{{/each}}
</script>
I'm still pretty green on EmberJS, that's why I would like to ask for some suggestion/commment on out to correct this.
Thanks in advance!

Here is the jsbin working example:
http://jsbin.com/OlOJEwAX/4/edit?html,js,output
I've managed to get the links working but the undefined is also there rendered :S

Related

MeteorJS template placeholder

Iam getting started with MeteorJS/Iron Router/Blaze and I'm trying to figure out how to set placeholder for template.
I have a menu and a footer, which will change only partialy, but between them is the main content which should be based on current route. Point is that i need some sort of pointer, like in angular "ng-view".
Eg.
<menu></menu>
{{some sort of placeholder}}
<footer></footer>
and in router:
Router.route('/', function () {
//render some template exactly into placeholder, dont append it to the bottom
});
Maybe there is something wrong with my understanding of meteorjs templating, I just base my way of solving this problem on angular templating.
not sure I got your question but here is an answer:
You can do that with the {{> yield}} tag. It will define an dynamic area which will show the view corresponding to the current route.
You can also "design" a layout for your entire app, like you did, for example layout.html :
<template name="layout">
<div class="container">
<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="{{pathFor 'home'}}">My app</a>
</div>
</header>
<div id="main" class="row-fluid">
{{> yield}}
</div>
</div>
</template>
And tell Iron-Router that your app has to fit this layout :
Router.configure({
layoutTemplate: 'layout'
});
// Then just define your routes
Router.map(function() {
this.route('home', {path: '/'});
});
You may notice I used {{pathFor 'home'}} in the layout. Iron Router let you use route "names" so it won't do anything if you change the URL.
I suggest you read an awesome book called Discover Meteor !

Ember Nested Routes and rendering models

I have an invoice application generator and i want to show the invoices with all his transactions in 2 different ways, at the moment i can only do it in 1 way ( Edit Link)
On Edit link where i can see all my invoices and transactions
together ( it s how it works now)
On View link where i want to see only the specific Invoice information with his own transactions
and not any of the other invoices and informations
I have reproduced my case here
This is the route code
App.Router.map(function(){
this.resource('invoices', function(){
this.resource('invoice', { path:'/:invoice_id' }, function(){
this.route('edit');
});
this.route('create');
});
});
The problem is that as long as i am inside the invoices resources i am sharing the invoices templates where everything is generated, but is there a way where i can see only my single invoice with his own transactions inside the invoices route? Is it achievable with the same Route Code? What's the best way to get this done?
<script type="text/x-handlebars" id="invoices">
<div class="large-12 columns">
{{#link-to "invoices.create"}} Add Invoice {{/link-to}}
</div>
<ul class="fatturas-listing">
{{#each invoice in model}}
<li>
{{#link-to "invoice" invoice}}
Edit {{invoice.title}}
{{/link-to}}
</li>
<li>
{{#link-to "invoice" invoice}}
View {{invoice.title}}
{{/link-to}}
</li>
{{else}}
<li>no fatturas… :(
</li>
{{/each}}
</ul>
{{outlet}}
</script>
I don't get your 'edit' part. The problem you have right now is the outlet defined in the invoices template, all sub routes will be rendered in here, so you cannot show an invoice without its parent (invoices) content.
I think the most common way is to remove the outlet and show all invoices in the InvoicesIndex route. Clicking an invoice will then go to a single invoice (a new page without showing the invoices list from the InvoicesIndex route).

Ember losing active trail

Hi I have the following Routes in ember:
App.Router.map(function(){
this.resource('meat', function() {
this.resource('poultry', function() {
this.route('chicken');
this.route('duck');
});
});
});
My templates look like this:
<script type='text/x-handlebars' id='meat'>
<div>{{outlet}}</div>
</script>
<script type='text/x-handlebars' id='poultry'>
Poultry
<br/><br/>
{{#link-to 'poultry.chicken'}}Chicken{{/link-to}}
{{#link-to 'poultry.duck'}}Duck{{/link-to}}
<br/><br/>
<div>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="poultry/chicken">
<h4>Chicken</h4>
</script>
<script type="text/x-handlebars" id="poultry/duck">
<h4>Duck</h4>
</script>
The problem is, when I click on the 'Duck' link, I lose my active trail to 'Poultry'.
I can't figure it out, the path is correct, but the active classes are gone.
Here is a jsbin: http://emberjs.jsbin.com/yularepare/2/
Thanks!
The code in your comment is a little different than the JSBin. You didn't include the application template. Here it is:
<script type='text/x-handlebars' data-template-name='application'>
{{#link-to 'poultry.chicken' }}Poultry{{/link-to}}
<br/><br/>
<div>
{{outlet}}
</div>
</script>
You're losing the active class because you're linking straight to 'poultry.chicken', not 'poultry'. It isn't a parent route, but a sibling route. If you want to keep the active class, change you link-to to:
{{#link-to 'poultry'}}Poultry{{/link-to}}
and it should work fine. Working JSBin: http://jsbin.com/fefucalaqi/1/edit
EDIT: comment asked how to handle redirect to first result. Adding here.
App.PoultryIndexRoute = Ember.Route.extend({
redirect: function() {
// write some code to get to your first result here.
this.transitionTo('poultry.chicken');
}
});
Now you'll get both: active class on all poultry routes and you'll show the first one if none were selected.

Making divs clickable - Ember view for action on multiple elements

I am developing a Cordova application with help from Ember. I have many dynamic elements in my application. These are Bootstrap thumbnails that link to other routes when clicked.
I want to make these thumbnails clickable. If I use Views, I will have to write unique views for all the thumbnails.
I have heard about mixins. Can a general View be defined that will :
Pass a model
Render a template for a route with the model
In other words, since each view semantically performs the same action, I want to be able to do something similar to
{{#each}}
{{#view App.AllView this}}
.
{{/view}}
{{/each}}
in the template and in the view :
App.AllView = Ember.View.extend({
click: function(evt, model){
this.controllerFor('route').set('content', model);
this.transitionTo('route');
}
});
UPDATE
Following #givanse's answer, I made the following component
<script type="text/x-handlebars" data-template-name="components/thumbnail-view">
<div {{bind-attr class=class}}>
<div class="thumbnail">
<div class="caption">
{{name}}
</div>
<img {{bind-attr src=image }}>
</div>
</div>
</script>
and used it in my template :
<script type="text/x-handlebars" data-template-name="types">
<div class="row">
{{#each model}}
{{thumbnail-view action="goToCategory" class="col-xs-12" param=this name=name image=image}}
{{/each}}
</div>
</script>
with an Ember component :
Pioneer.ThumbnailViewComponent = Ember.Component.extend({
click: function(){
this.sendAction('action', this.get('param'));
}
});
The action goToCategory is defined in my ApplicationRoute
Hope this helps someone!
What you need is Components, something like:
<script data-template-name="index">
{{#each}}
{{img-thumbnail imgId="id/path/name"}}
{{/each}}
</script>
<script data-template-name="components/img-thumbnail">
{{! whatever you need to make your thumbnail }}
</script>
App.ImgThumbnailComponent = Ember.Component.extend({
// handle events, classes, etc.
});
See:
http://emberjs.com/guides/components/
http://emberjs.com/api/classes/Ember.Component.html

Getting active click working on Components in EmberJS?

I have a JSON structure that I'm passing into a Toolbar to try out dynamic compartmentalization in EmberJS. It looks like this:
{
draggable: true,
buttons: [
{label: "Portrait", action="vertical"},
{label: "Landscape", action="horizontal"}
]
}
I'm using it in a picture viewer that turns a photo vertically and horizontally. Because it's supposed to be a reusable toolbar for other parts of the application, I made it a Component and hooked the click event to the parent controller so it would turn the picture on click. I wanted the button to also get the active class like it does in other examples, but I think that's not working because of the embedded nature of the buttons. How do I get the button that gets clicked to get the active class so I can add css to it?
I tried setting an isActive property in each of the button objects in the model when init gets called and then setting that as true via the action function but I couldn't get observables to work with nested data structures. Do I have to make each button a separate component or can I avoid that?
Thanks for the help.
Templates
<script type="text/x-handlebars" data-template-name="photo-gallery">
<div id="PictureApp"></div>
{{#if toolbar}}
{{ui-toolbar options=toolbar buttonClicked="changeOrientation"}}
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="components/ui-toolbar">
{{title}}
<div class="overlay">
<div class="toolbar draggable">
{{#if draggable}}
<div class="header draggable-handle"></div>
{{/if}}
<ul>
{{#each buttons}}
<li{{action "clicked" this}}>{{label}}</li>
{{/each}}
</ul>
</div>
</div>
</script>
JS
App.UiToolbarComponent = App.Component.extend({
actions: {
clicked: function(context){
console.log(context);
this.sendAction("buttonClicked", context.action);
}
},
didInsertElement: function(){
if(this.get("draggable")) {
this.$(".draggable").draggable({handle: ".draggable-handle"});
}
}
});
It seems like you're on the right track. I think you could set the active property property on the button, however, you still need to set clear the active flag on any other button.
Inside the clicked action:
clicked: function(context){
console.log(context);
this.buttons.setEach('active', false);
context.set('active', true)
this.sendAction("buttonClicked", context.action);
}
Then on your template you can bind the class:
{{#each buttons}}
<li {{bind-attr class=active}} {{action "clicked" this}}>{{label}}</li>
{{/each}}

Categories

Resources