Editing Handlebars templates with ember and ember-cli - node.js

Hey so my problem is probably simple as I am brand new to ember and ember-cli, from what I understand you simply edit an applications HBS template containing the html, IE.
app/templates/settings.hbs
however my problem is that when I edit one of these files and restart the entire stack, no change is reflected - furthermore I'm basically just trying to create some minor changes to an already created stack by entering an if conditional to find the controller name and display content if it matches what im looking for,
for example
{{#if controller.name == "settings"}}
// diff lis
{else}
// normal lis
{#endif}
most importantly here, any changes I make at all to the HBS template does not seem to be reflected live, any idea why?

In addition to #Oren answer, if you're using ember 1.10 you can take advantage of handlebars subexpressions and write your own eq helper which could be used in more situations. For instance:
Ember.Handlebars.registerBoundHelper('eq', function(left, right) {
return left === right;
});
And then in your template
{{#if (eq name "settings") }}
// diff lis
{{else}}
// normal lis
{{/if}}
// ...
{{#if (eq something otherstuff) }}
// show this
{{else}}
// show that
{{/if}}
Live sample http://emberjs.jsbin.com/mezoxiqavi/1/edit

Handlebars does not have an equality helper in the form that you have posted. (See this list for a list of all of the built in helpers.)
Instead, what you need to do to make your code work is create a property on your controller:
IsNameSettings: function(){
return this.get('model.name') === 'settings';
}.property('model.name');
And change your template to use this property (note that you also have {{/endif}} which needs to be changed to {{/if}} [see the link above]):
{{#if controller.IsNameSettings}}
// diff lis
{else}
// normal lis
{/if}
See whether after changing your handlebars template to valid syntax as I described results in the page live updating when you are waiting for a live reload. Confirm that after saving these changes, you see output from ember-cli indicating a successful build. Check for output in the terminal along the lines of:
version: 0.1.12
Livereload server on port 35729
Serving on http://0.0.0.0:4200/
Build successful - 8891ms.

Related

handlebarsjs get the value of the selected option dynamically

I've been working with pug/jade a little bit and now I'm trying to build the same project using handlebars.
I have this iteration that renders a few options:
<select id="myselect" name="myselect">
{{#each categories}}
<option value="{{id}}">{{title}}</option>
{{/each}}
</select>
A bit further down the code I need to render some items dynamically based on the selected item from myselect.
Any idea how I can grab it dynamically? Basically the same way like onchange() works in plain javascript.
When you use any kind of tempting engine (handlebars, jade, ejs, etc). You cannot bind data after the response sent to the client. You have to write some client side javascript code to achieve that.
As an alternative you can use handlebarjs on client side. Follow this link
But this may need to be used carefully, since you are using the same template engine on your server side.

How to use equality in handlebars build-in #if helper

In handlebars how can I say for example:
{{#if view_type == "medium"}}
// Do something
{{/if}}
Not simply :
{{#if view_type}}
// Do something
{{/if}}
Im am using it in NodeJs
Im looking for solution without registerHelper()
There's no solution without a new helper. What I would suggest you is to switch from handlebars to Swig, which, the syntax, is pretty similar.
http://paularmstrong.github.io/swig/docs/
It is easily implementable.
If you are trying to do an IF I guess you are at the beginning of your project so it could be an option.

Meteor Iron-Router Layout Rendering

We have implemented a layout where the main content resides in dynamic sidebars. We defined following layoutTemplate:
<template name="layout">
{{> content}}
{{> leftbar}}
{{> rightbar}}
<nav class="navigation">
{{#if currentUser}}
{{> navigation_logged_in}}
{{else}}
{{> navigation_logged_out}}
{{/if}}
</nav>
</template>
We include e.g. the rightbar template in the layout template.
<template name="rightbar">
<aside class="rightbar">
<button id="closeRightBar" class="close-cross"></button>
{{yield 'rightbar'}}
</aside>
</template>
The rightbar template includes the rightbar yield where we yield the specific content into.
We have implemented following RouteController:
UserShowRouter = RouteController.extend({
before: function() {
var username = this.params.username;
if(App.subs.user) {
App.subs.user.stop();
}
App.subs.user = Meteor.subscribe('user', username);
},
waitOn: function () {
return Meteor.subscribe('user');
},
data: function() {
return Meteor.users.findOne({'profile.username': this.params.username});
},
action: function() {
this.render('profile', {to: 'rightbar'});
}
});
What we wanted to achieve is that for example the profile template is yielded into the rightbar yield and get's updated and re-rendered as the data changes.
The problem is now that the sidebars are dynamically animated, shown and hidden. Now every time the profile template gets re-rendered also the layout template gets re-rendered. Why is that? We thought one of the purposes of yield regions is that the whole site doesn`t need to be re-renderd. Now when the layout gets re-rendered the whole css of the animations are set back to the original values.
We now have tried several different approaches, but none of them seems to be a good and clean solution. Is there a way to keep the layout template from being re-rendered and just keep the yield region and template up-dated? Any suggestions or alternatives would be highly appreciated.
As I understand it, the behavior in which re-rendering of your templates "bubbles up" and causes re-rendering of their parent templates is not particular to iron-router or the way your code is implemented, but is inherent in Spark. Iron-router's {{yield}} pattern does not alter this behavior, as far as I can tell from its documentation.
The good news is that Spark is set to be replaced imminently with a newer, more fine-grained rendering engine, currently codenamed "Spacebars," which should alleviate the concern.
Here is a preview of the new rendering system:
https://github.com/meteor/meteor/wiki/New-Template-Engine-Preview
This talk from a week ago is also excellent at describing the benefits coming through the new rendering engine (while fairly long, an overview is given in the first 5 minutes):
https://www.youtube.com/watch?v=aPf0LMQHIqk
As for your options today, you can:
a) Use the {{#constant}} and {{#isolate}} parameters to try to limit re-rendering.
b) Work from a development branch as described in the link above:
You can play with the current work-in-progress version of the code using the template-engine-preview-4 release tag (run your app with meteor --release template-engine-preview-4), or by checking out the shark branch (it's an internal codename).
c) Best of all if the timeframe of your project allows is to allow the re-rendering to continue until Meteor 1.0 hits and "Spacebars" resides on the main branch - it sounds like this is 1-3 months away.
I think that the reason your layout template gets rerendered is because the data hook you implemented uses a reactive data source. If the current user object changes, the router probably decides to rerender the whole page because there is no simple way to decide which parts exactly depend on your reactive data.
If I'm right, a simple solution to your problem is to create a user helper that will fetch the necessary data only where they're actually needed, e.g.
Template.profile.user = function () {
return Meteor.users.findOne({/*...*/});
}
Then you can use it in your profile template along with the with helper (sic!), i.e.
{{#with user}}
...
{{/with}}
to prevent multiple calls to the Template.profile.user function.
Also, if I were you, I would use the data hook only for data which is required by templates in my layout.

Render partial view with jade on select change

I need to do the following,
I have a <select> (a list of team names), when the user selects a team, I get relevant information re: the team and display it.
How do I do this in jade?
I'm trying the following, (but I'm wrong obviously, I don't see a lot of documentation out there).
Briefly, I'm doing a include test.jade on my main page, and a res.render('test', {team: team_obj});
jade:
h1 #{team}.name
h2 #{team}.homeGround
h3 #{team}.manager
h4 #{team}.aka
nodejs:
collection.findOne(query, function(err, team_obj){
res.render('test', {team: team_obj});
});
I'm getting the information correctly in team_obj.
Get the following error when I run the app,
team is not defined
Now this is happening because test.jade is getting rendered before I feed it the team_obj.
Questions:
1) Am I doing this right? is include the correct way of partially rendering jade views? if yes, how do I make sure it renders only when the user has selected an option?
2) Is there a partial views concept in jade I'm unaware of?
1) you should use #{team.name}
2) you can't change the team object once the selector is changed. the template was rendered once with the database result. - such functionality should be handled by client side JavaScript and AJAX calls. partials in templates are just a way to share common pieces of templates, and its done in Jade via include.
I don't know what you're rendering and including and when.. but id you use a template variable like #{team.name} you have to make sure that the template was rendered with the team object.

Passing arguments from node.js to knockout.js through ejs

I have a node.js that consumes mongodb data and outputs lists using knockout.js
When i invoke the view i pass a json structure using
res.render('list', { items:json });
In the list.ejs template page i've defined a hidden element:
<input type="hidden" id="hidden" value="<%= items %>">
and in .js file i read its value:
var json=$("#hidden").val();
var tkts=jQuery.parseJSON(json);
var vm=new AppViewModel(tkts);
Well...it runs but i think (hope) there must be a better way do it ... is there a way to avoid a hidden html var, for example?
Currently I can think of three ways to do this.
1.) Assign the data to a variable in your JavaScript code:
<script type="text/javascript">solution1 = {"name": "solution1"}</script>
solution1
2.) Add a data-attribute to an element of your liking:
<div id="solution2" data-value='{"name": "solution2"}'></div>
JSON.parse(document.getElementById('solution2').dataset.value)
3.) Use the script tag and choose a different content type than text/javascript or application/javascript
<script id="solution3" type="script" type="text/json">{"name": "solution3"}</script>
JSON.parse(document.getElementById('solution3').innerHTML)
Live demo
http://jsfiddle.net/bikeshedder/sbjud/
Personal note
It might sound boring, but the first option is probably the best choice. It is fast, requires as little code as possible and just works. I don't see a reason why you would want to have your data in a string first if you can have it as JavaScript data right away.
You could add an inline script if you are serving up a full page... Of course this would pollute the global namespace.
<script>
var tkts = <%= items %>;
</script>
If you are using AJAX to get this page... then break it into two AJAX requests... one of them gets the template, and the other one can get the list of items (as a JSON request). They could run in parallel so it might even be quicker.

Resources