I have an ember route webtest contained within the file routes/webtest.js:
export default Ember.Route.extend({
model: function() {
return {
title: "Does not appear"
};
}
});
I have the matching template contained within templates/webtest.hbs
<div class="container">
<h2>Title: {{title}}</h2>
</div>
when I navigate to the page /webtest in my web browser with ember serve
the resulting page has the title: text, but not the text does not appear
I have been to multiple ember pages, and I have the same code working here:
http://jsbin.com/neheru/6/edit?html,js,output
The goal is to be able to have a variable accessible from within the template webtest that can be accessed by a route.
FYI I'm trying to get it to the template so I can pass variables to a component
The variable should be {{model.title}}
You can log out variables from your template with
{{log title}}
{{log controller.title}}
{{log model.title}}
This might help you to debug faster.
You should then be able to pass data in to our component with something like:
{{my-component title=model.title}}
Related
Within one of my route's renderTemplate method, I've tried to render a different template by using this.render:
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render( 'dashboard', {
into: 'admin'
});
}
});
But the application within the browser is empty and the console shows the following:
Assertion Failed: You attempted to render into 'admin' but it was not
found
After this error message, I thought that the "admin" template might simply not be existent, but it it's there. Both the "dashboard" and the "admin" template are loaded. And the weirdest thing: I'm able to use this.render( 'dashboard' ) and this.render( 'admin' ) and both of them work fine.
What am I doing wrong? I've even added an {{outlet}} tag to the "admin" template.
If you want to render into admin then you have to use named outled inside your template (associated with route file you write renderTemplate). So, inside your template use:
{{outlet 'admin'}}
edit
I'm not really sure what to do right now. Just to clarify: "admin" is
a hbs template which contains a {{outlet}}. And into this outlet tag,
I want to load 'dashboard.hbs'. And after that, I want to output the
whole thing.So in which file do I need
I'm assuming you want to render these 2 templates from another unassociated route. In that case you could add {{partial 'dashboard'}} to admin.hbs and use just this.render('admin') in your IndexRoute.
edit 2
Inside your IndexController specify partialName: 'dashboard' and change it dynamically in your code and replace {{partial 'dashboard'}} with {{partial partialName}}. It should work dynamically and you can swap out dashboard for another templates.
URL to current version of my project
Here is the code for my project
Background:
I am making a blog using meteor and iron-router. I want to use a single controller for several different "category pages," which filter a list a blog articles in the yield region.
The Problem:
The article list does not get rerendered when the URL changes. I.e. the article list is not reactive. Interestingly, if I navigate back to the home page, the correct article list shows up.
The Question:
How do I make that article list change when I change between different routes on the category route controller?
Some example code:
Please note that the code for this whole project is available here.
Here is my Route Controller:
CategoryController = RouteController.extend({
action: function(){
this.render();
},
template: 'category',
data: function(){
return {category: this.params.category};
}
});
CategoryController.helpers({
articles: function(){
return Articles.find({category: this.params.category});
}
});
And here is the template it is rendering:
<template name='category'>
<div class="container">
<h2>{{category}}:</h2>
<ul>
{{#each articles}}
<li>
{{#linkTo route="article.show"}}
{{title}}
{{/linkTo}}
</li>
{{/each}}
</ul>
</div>
</template>
Resources/Updates:
Read this article on Meteor Reactivity and the Deps Package. Very interesting, but after trying some Deps.autoruns in different places, I don't think that this is the answer.
Currently trying to make different "category" routes inherit from the controller.
The article list does not change because the Template helper is not using a reactive data source. You may use the RouteController.getParams method to establish a reactive dependency on route parameters as shown below.
CategoryController.helpers({
articles: function(){
var controller = this;
var params = controller.getParams();
return Articles.find({category: params.category});
}
});
From Iron Router documentation:
Note: If you want to rerun a function when the hash changes you can do
this:
// get a handle for the controller.
// in a template helper this would be
// var controller = Iron.controller();
var controller = this;
// reactive getParams method which will invalidate the comp if any part of the params change
// including the hash.
var params = controller.getParams();
By default the router will follow normal browser behavior. If you
click a link with a hash frag it will scroll to an element with that
id. If you want to use controller.getParams() you can put that in
either your own autorun if you want to do something procedural, or in
a helper.
On my server side I have a product model with a property called 'image' and it is the name of the image with it's extension, I'm using ember app kit and I'm placing my image in the public/assets folder and I want to reference that along with the file name so that it correctly displays the image on the page. So in my decent knowledge of ember I made an array controller (since I'm working with a set of products) and I took the property and just returned it with a string on the front referencing that path. But I'm getting nothing displayed to the page, not even a broken image.
I've placed this controller in controllers and called it products.js
var ProductsController = Ember.ArrayController.extend({
assetPath: function() {
alert(this.get('image'));
return '../assets/' + this.get('image');
}.property('image')
});
export default ProductsController;
and my template is just in templates and is called products.hbs and looks pretty basic
{{#each}}
<div class="item">
<h2>{{name}}</h2>
<p>{{price}}</p>
<p>{{image}}</p>
</div>
{{/each}}
First of why am I not getting anything when referencing this property? And second is this the "ember way" to do it or should it be done somewhere else?
Just found this stack overflow (not sure why this didn't turn of the first time I searched)
Inserting a Model Property into an Img Element URL in Ember
I forgot you could define these on the model as well.
so I just did this...
var Product = DS.Model.extend({
...
image: DS.attr('string'),
assetPath: function(){
return "/assets/"+this.get('image');
}.property('image')
});
I'm trying to wrap my head around Ember at the moment, but all the magic is making this difficult.
I've set LOG_TRANSITIONS: true and Ember.LOG_BINDINGS = true; which gives me some minimal logging to the console, but I really need more than that.
I'm particularly struggling with seeing what's going on when Ember is automagically creating Controllers, Views and Templates.
Is there a way to log this aspect of the framework - to see where Ember is looking for Templates/Views/Controllers and when it is creating one on its own volition.
For example, I have the following routes set up:
App.Router.map(function() {
this.route("example_items", {path: "/"});
});
with:
App.ExampleItemsRoute = Ember.Route.extend({
model: function() {
return App.ExampleItem.find();
}
});
Ember renders my ApplicationController and its application.handlebars template:
<header class="page-header">
<h1>Application Template</h1>
</header>
{{outlet}}
But fails to render my example_items.handlebars template. I get no exception or warning, and if I check the DOM, I can see ember has created a generic view in its place.
The bindings logging shows me that Ember has transitioned to example_items, but it seems it hasn't used either my ExampleItemsController, ExampleItemsView or template.
How can I debug a situation like this if I receive no errors or messages?
Edit:
App.ExampleItems View:
App.ExampleItemsView = Ember.CollectionView.extend({
templateName: 'example_items'
});
And App.ExampleItemsController:
App.ExampleItemsController = Ember.ArrayController.extend({
});
I'm particularly struggling with seeing what's going on when Ember is automagically creating Controllers, Views and Templates.
Is there a way to log this aspect of the framework - to see where Ember is looking for Templates/Views/Controllers and when it is creating one on its own volition.
Yes. With the latest ember you can now LOG_ACTIVE_GENERATION to see console.log output whenever ember generates something for you.
Another new setting that might be helpful is LOG_VIEW_LOOKUPS
Here's your problem: CollectionView won't use your template. It takes an array as its content property (usually set up as a binding to the controller) and creates childViews manually. Without a content set it'll appear as a blank view.
If you add classNames: ['my-view'] to your view definition, you should see that the view it's instantiating and inserting is actually your view class, just empty. Add contentBinding: 'controller' and it should render itemViews for each item in the array, as well.
I am new to Javascript and just started fiddling around with Meteor out of curiosity. What really surprises me, is that it seems that all HTML content gets combined into a single page.
I suspect there is a way to introduce some handling of URLs directing to special pages. It seems that the "todo" example is capable of doing this via some kind of Router class. Is that the "canonical" way of URL handling?
Assuming I can handle URLs, how would I structure my HTML code to display separate pages? In my case they could each have completely separate sets of data, so no HTML code needs to be shared at all.
Jon Gold's answer used to be correct, but as of Meteor 0.5.4:
Work has now shifted to Iron Router. Please consider using IR instead of Router on new projects!
Thus, the current "canonical" way to do this is probably to use IronRouter.
As far as I am aware, there is currently no out of the box way to do this.
What I suggest to do, is to use Backbone.js smart package.
Backbone.js comes with the push-state Router, and if the user's browser doesn't support that it will fallback to hash urls.
In your meteor app directory type this meteor add backbone.
Then somewhere in your client-side code create a Backbone.js Router like so:
var Router = Backbone.Router.extend({
routes: {
"": "main", //this will be http://your_domain/
"help": "help" // http://your_domain/help
},
main: function() {
// Your homepage code
// for example: Session.set('currentPage', 'homePage');
},
help: function() {
// Help page
}
});
var app = new Router;
Meteor.startup(function () {
Backbone.history.start({pushState: true});
});
Then somewhere in your Handlebars template, you can create a helper that will render a page based on the value set in Session's "currentPage".
You can find more information about backbone.js router here: http://backbonejs.org/#Router
Also relevant information on how to create a Handlebars helper method in Metoer here: http://docs.meteor.com/#templates
Hope this helps.
Meteor-Router makes this really easy. I've been using it in some apps I've been building with Telescope as a good reference. Have a look at Telescope's router.js
To use it…
mrt add router
In client/router.js:
Meteor.Router.add({
'/news': 'news', // renders template 'news'
'/about': function() {
if (Session.get('aboutUs')) {
return 'aboutUs'; //renders template 'aboutUs'
} else {
return 'aboutThem'; //renders template 'aboutThem'
}
},
'*': 'not_found'
});
In your template…
<body>{{renderPage}}</body>
I found the same problem. When the code gets bigger it is difficult to keep the code clean.
Here goes my approach to this problem:
I separate the different html pages as I would do with another web framework. There is an index.html where I store the root html page. And then for each big functional part I create a different template and place it in one different html. Meteor then merges them all. Finally I create a session variable called operation where I define what to show at each time.
Here goes a simple example
index.html
<head>
<title>My app name</title>
</head>
<body>
{{> splash}}
{{> user}}
{{> debates}}
</body>
then in splash.html
<template name="splash">
{{#if showSplash}}
... your splash html code goes here...
{{/if}}
</template>
then in user.html
<template name="user">
{{#if showUser}}
... your user html code goes here...
{{/if}}
</template>
and so on ...
In the javascript code then I check when to print each template using the Session variable, like this:
Template.splash.showSplash = function(){
return Session.get("operation") == 'showSplash';
}
Finally the Backbone Router manages this Session variable
var DebateRouter = Backbone.Router.extend({
routes: {
"": "showSplash",
"user/:userId": "showUser",
"showDebates": "showDebates",
// ...
},
splash: function () {
Session.set('operation', 'showSplash');
this.navigate('/');
},
user: function (userId) {
Session.set('operation', 'showUser');
this.navigate('user/'+userId);
},
// etc...
});
I hope this pattern is helpful for other Meteor developers.
This is my hacky solution to routing :
https://gist.github.com/3221138
Just put the page name as the template name en navigate to /{name}