Link-to cannot find nested resource on passing two models - ember.js

Here is the app i am learning to build.
categories has many products.
Accordion of category - heading and products as body is in categories template
router.js
MyApp.Router.map(function () {
this.resource('categories', {path: '/'}, function () {
this.resource('category', { path: '/:category_id'}, function () {
this.resource('product', {
path: '/:product_id'
});
});
});
});
My categories handlebar
<div class="panel-group" id="accordion1">
{{#each category in model}}
{{view MyApp.AccordionView context=category}}
{{/each}}
</div>
and my accordion view
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
{{#view MyApp.AccordionTitleView }}{{name}} {{/view}}
</h4>
</div>
<div {{bind-attr id=id}}class="panel-collapse collapse">
<div class="panel-body">
<table class="table">
<tbody>
{{#each products itemController="product"}}
<tr><td>{{#link-to 'category.product' category content }}{{content.name}}{{/link-to}}</td></tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
U P D A T E S
my issue got resolved by changing
{{#link-to 'category.product' category content }} in my accordion view to
{{#link-to product' category content }}
but as per ember guides
Ember guides
I can pass two model like this sample code
<p>
{{#link-to 'photo.comment' 5 primaryComment}}
Main Comment for the Next Photo
{{/link-to}}
</p>
i dont understand if its because my router hierarchy. but in any case i think it should give some nice error. I an a noob wonder what experts think on this

You have to use 'product' in your link-to instead of 'category.product'.
This is because in MyApp.Router.map() you made product a resource, not a route.
Resources' route names are unprefixed, whereas routes' route names are prefixed with their parent resource.
See http://emberjs.com/guides/routing/defining-your-routes/#toc_nested-resources

Related

Ember Error while processing route: index Assertion Failed: Unable to find fixtures for model

I have my index page where i show a list of invoices where the user can click to create and edit them, i am using DS.FixtureAdapter in my adapter
The problem is that i get this error
Error while processing route: index Assertion Failed: Unable to find fixtures for model
If in my model i reopen the class like this, everything works fine
Invoice.reopenClass({
FIXTURES: [
{
id : '1',
name : 'Invoice num 1',
transactions: [1]
}
]
});
So i assume that i am doing something wrong in my template where i am saying if there are not invoices show me "no invoices..."
<div class="row">
<div class="large-6 columns">
<h3>View Invoices</h3>
<ul class="invoices-listing">
{{#each invoice in model}}
<li>
{{#link-to "invoices.show" invoice}}
{{invoice.name}}
{{/link-to}}
</li>
{{else}}
<li>no invoices… :(</li>
{{/each}}
</ul>
</div>
<div class="large-6 columns">
<h3>Edit Invoices</h3>
<ul class="invoices-listing">
{{#each invoice in model}}
<li>
{{#link-to "invoices.edit" invoice}}
{{invoice.name}}
{{/link-to}}
</li>
{{else}}
<li>no invoices… :(</li>
{{/each}}
</ul>
</div>
<div class="large-12 columns">
Invoices: {{InvoicesCount}}
</div>
<div class="large-12 columns">
{{#link-to "Invoices.create" class="create-btn"}} Add Invoice {{/link-to}}
</div>
</div>
Routes Index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.find('fattura');
}
});
This looks like a problem only when i start the ember server because for instance if i start creating and deleting invoices and i want to delete all of them the index page shows correctly "no invoices..."
You'll always need to set up fixtures even if you want to start with no records. Ember still needs somewhere to go look for them and will error if you don't at least have a fixture with an empty array.
So you can just start your project with this in your model:
Invoice.reopenClass({
FIXTURES: []
});

each vs each foo in model, differences and issue with link-to undefined

I'm trying to do a list of product items and make them so when you click the image or title it will show a single page/template with the more info, etc.
But, when ever I use {{#each product in model}} the link-to just returns an undefined.
Heres what I have
App.Router.map(function(){
this.route('about', { path: '/aboutus' } );
this.resource('products');
this.resource('product', { path: '/products/:title' } );
this.resource('contacts');
});
App.ProductsRoute = Ember.Route.extend ({
model: function(){
return App.PRODUCTS;
}
});
// Logging out Params from the Route
App.ProductRoute = Ember.Route.extend ({
model: function(params){
return App.PRODUCTS.findBy('title', params.title);
}
});
App.PRODUCTS = [
{
title: 'Flint',
price: 99,
description: 'Flint is a hard, sedimentary cryptocrystalline form of the mineral quartz, categorized as a variety of chert.',
isOnSale: true,
image: 'images/flint.png'
},
{
title: 'Kindling',
price: 249,
description: 'Easily combustible small sticks or twigs used for starting a fire.',
isOnSale: false,
image: 'images/kindling.png'
}
];
when I use this method {{#each product in model}} i get undefined
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each product in model}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='product.image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{product.title}}</h2>
<p class="product-description">{{product.description}}</p>
<p><button class="btn btn-success">Buy for ${{product.price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
<script type='text/x-handlebars' data-template-name='product'>
<div class="row">
<div class="col-md-7">
<h2>{{title}}</h2>
<p>{{description}}</p>
<p>Buy for ${{price}}</p>
</div>
<div class="col-md-5">
<img {{bind-attr src='image'}} class='img-thumbnail img-rounded' />
</div>
</div>
</script>
but when I use just {{#each}} it returns normally BUT it warns me this: DEPRECATION: Using the context switching form of {{each}} is deprecated. Please use the keyword form ({{#each foo in bar}}) instead.
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{title}}</h2>
<p class="product-description">{{description}}</p>
<p><button class="btn btn-success">Buy for ${{price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
which one should I use and how do I fix the undefined error? I'm guessing it has to do with the App.ProductRoute but can't figure it out, still new to ember :l
You should use
{{#each product in model}}
and to fix your undefined use the following:
{{#link-to 'product' product }} ...title... {{/link-to}}
When you use {{#each}} the context of this gets switched to each item in the loop, which is sometimes confusing and is being deprecated. When you use the {{#each product in model}} version, the context of each item through the loop is product and this remains whatever it was you entered each

How to set itemController for instance variable in ember.js indexController?

I have a Ember.js page that displays a table of items and shows details of one of the items when it is selected. The controller looks like this:
CV.IndexController = Ember.ArrayController.extend({
itemController: "CurrVitae",
selectedCurrVitae: false,
actions: {
selectCurrVitae: function(currVitae) {
this.set('selectedCurrVitae', currVitae)
}
}
});
And the index controller is used in a template like this:
<div class="container">
<div class="curr-vitae-list">
{{#each curr_vitae in controller}}
<div class="curr-vitae-item row">
<div class="col-sm-2" {{action selectCurrVitae curr_vitae}}>
{{curr_vitae.name}}
</div>
<div class="col-sm-2">
<!-- NOTE: This method is defined on the item
controller (not the model) so the itemController is
available at this point. -->
{{curr_vitae.createdAtDisplay}}
</div>
<div class="col-sm-7">
<div class="embedded-cell">
{{curr_vitae.summary}}
</div>
<div class="embedded-cell">
{{curr_vitae.objective}}
</div>
</div>
</div>
{{/each}}
</div>
<div class="curr-vitae-view">
<h2>Details</h2>
<!-- EDIT: I have tried setting this
as {{#if selectedCurrVitae itemController="currVitae" }}
to match the way the #each handles item controllers but that did
not seem to work -->
{{#if selectedCurrVitae }}
<!-- NOTE: Down here, however, the item controller is not available
so I can't use methods defined on the item controller for the
currently selected instance. -->
{{ partial "cv_index_details" }}
{{/if}}
</div>
</div>
Question: The problem I'm running in to is that the itemController I've set in the index controller is not available when rendering the selectedCurrVitae in the cv_index_details.
More details:
Specifically, in the partial I want to reuse a editor component (taken from Noel Rappin's Ember.js book). So if the cv_index_details partial looks like this:
<h3 class="selected_cv">{{selectedCurrVitae.name}}</h3>
<div class="row selected_cv_summary">
<h4>Summary</h4>
{{block-editor emberObject=selectedCurrVitae propName="summary" action="itemChanged"}}
</div>
<div class="row selected_cv_experiences">
<h4>Experiences</h4>
{{#each experience in selectedCurrVitae.experiences itemController="experience"}}
{{ partial "experience_detail" }}
{{/each}}
</div>
So in this template, the itemChanged action is not found for the selectedCurrVitae instance. However, I use the same block-editor component for the experience instance and that works correctly; the itemChanged action defined on the ExperienceController is found.
selectedCurrVitae is outside of the itemController, the itemController is only applied inside the each (on each item, hence the name).
Probably the easiest way to accomplish this will be to reuse the item controller and use render.
Template
{{#if selectedCurrVitae }}
{{ render "cv_index_details" }}
{{/if}}
Controller
CV.CvIndexDetailsController = CV.CurrVitaeController.extend();
Or
Template
{{#if selectedCurrVitae }}
{{ render "currVitae" }}
{{/if}}
View
CV.CurrVitaeView = Ember.View.extend({
templateName: 'cv_index_details'
});

Ember.js best practices for adding subnav

I was curious as to what the best way is to implement sub navigation in Ember. In application.hbs I have the main nav with 'about', 'programs', etc. When 'about' is clicked I would like another list of pages to display on the row directly below the main nav. I'm already using {{outlet}} inside of application.hbs so I can't put another where I want the subnav to display.
Here's what I have:
<div class="row left-nav">
{{#linkTo "index"}}<img class="ew_logo" src="assets/ew.png">{{/linkTo}}
</div>
<div class="row nav">
<div class="large-12 colummns">
<ul class="inline-list top-nav">
<li><h6>ABOUT</h6></li>
<li><h6>//</h6></li>
<li><h6>CONDITIONS</h6></li>
<li><h6>//</h6></li>
<li><h6>PROGRAMS</h6><li>
<li><h6>//</h6></li>
<li><h6>TESTIMONIALS</h6></li>
</ul>
</div>
</div>
<div class="row subnav">
<div class="large-12 colummns">
// Would like SUBNAV to display here
</div>
</div>
{{outlet}}
You could use a named outlet and hook into the renderTemplate function of your route to render it into the right place, see here for a simple demo. (sorry, but the styles are obviously screwed)
Example if your named outlet is inside your index template then you could:
Index Template
...
<div class="row subnav">
<div class="large-12 colummns">
{{outlet 'subnav'}}
</div>
</div>
...
Subnav template
<script type="text/x-handlebars" id="subnav">
<h2>Hello I'm Subnav!</h2>
</script>
Index Route
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render(); // this renders the index template per se
// and this additional call renders the subnav template into the named outlet
this.render('subnav', { //the name of your template
outlet: 'subnav', //the name of the named outlet
into: 'index' //the name of the template where the named outlet should be rendered into
});
}
});
Note, you can have as many named outlet's as you want as long you render them like mentioned above, no matter what route you are in.
Hope it helps.

How to render multiply models in ember js

I have 3 models currency, income and income_operations. I wanna to render them on some route. What is the right way to do it? How can i render three models on one page?
UPD: This models don't have any associations between them.
route.js.coffee
#route 'addincome', { path: 'operations/addincome' }
EmberMoney.AddincomeRoute = Ember.Route.extend
model: ->
EmberMoney.IncomeOperation.find()
templates/addincome.handlebars
<div class="row container-bg"><br>
<div class="span6">
<ul>
{{#each operation in controller}}
<li>{{operation.sum}}</li>
{{/each}}
</ul>
</div>
<div class="span6">
{{outlet}}
</div>
</div>
// I want to render here more models! For example:
<ul>
{{#each income in incomes}}
<li>{{income.name}}</li>
{{/each}}
</ul>
Not tested, but in the route's setupController you could:
# excuse the coffeescript...
setupController: (controller) ->
controller.set('incomes', App.Income.find());
then in your template:
<ul>
{{#each income in controller.incomes}}
<li>{{income.name}}</li>
{{/each}}