How do I make {{#each}} work with these templates? - javascript

I have been reading these tutorials on Spacebars.
Understanding Spacebars by David Burles
Meteor's Spacebars README on Github
Discover Meteor's Spacebars secrets
I think I can understand pretty good, but I am having this problem
i have the main.html template like this
<template name="main">
<div class="container">
<section id="bl-work-section">
<div class="bl-box">
<h4 class="sin">Próximo</h4>
<h2 id="titulo1" class="sin"></h2>
<h4 class="sin" id="sub1"></h4>
</div>
<div class="bl-content">
<h2>Lunes 25 de Noviembre del 2014</h2>
{{#each mostrarLunes}}
{{> Lunes}}
{{/each}}
<a></a>
</div>
<span class="bl-icon bl-icon-close"></span>
</section>
<!-- Panel items for the works -->
<div class="bl-panel-items" id="bl-panel-work-items">
{{#each mostrarLunes}}
{{showPromos}}
{{/each}}
</div>
</div>
</div><!-- /container -->
</template>
So like you guys see im calling 2 templates inside main template and that 2 templates look like this
Lunes.html Template
<template name="Lunes">
<ul id="bl-work-items">
<li data-panel="panel">
<div class="oferta">
<h3>Promocion: {{metadata.nombrePromo}} </h3><br><small>Descripcion:{{metadata.descripcionPromo}}</small>
</div></li><br><br>
</ul>
</template>
showPromos.html Template
<template name="showPromos">
<div data-panel="panel">
<div>
<h1>Estoy viendo esto en la segunda pagina </h1>
<h3>Nombre Promo {{metadata.nombrePromo}}</h3>
<p>Descripcion promo.{{metadata.descripcionPromo}}</p>
</div>
</div>
<nav>
<span class="bl-icon bl-icon-close"></span>
</nav>
</template>
So what is the problem? well if we look at the template Lunes and showPromos, i have a Data-Panel="panel", but its seems like that data panel don't work when i wrap that value on the {{each}} tags, because if i use, that {{each}} tags outside the data-panel selector it works, so its seems like its not working seems like they don't have connection.
so im asking if there is a way to connect that value? already try helper attributes like the 3rd link says, and don't work, the attributes helpers look like this
Template.main.helpers({
attributes: function () {
return {
dataPanel: "prueba",
}
}
});
Helper mostrarLunes
Template.main.helpers({
'mostrarLunes' : function(){
return Promociones.find({'metadata.diaOferta' : { $in: ['Lunes'] } });
}
});

Looks like the data context isn't set. Try creating a template helper for your other templates with the data (I don't understand Spanish so I'm assuming this is the MongoDB cursor you need...
Templates.lunes.helpers({
data: function() {
return Promociones.find({'metadata.diaOferta' : { $in: ['Lunes'] } });
}
});
Templates.showPromos.helpers({
data: function() {
return Promociones.find({'metadata.diaOferta' : { $in: ['Lunes'] } });
}
});

Related

Filter Events with collections

I have projects and workflows with separate collections.
collections:
Project = new Meteor.Collection("project");
Workflow = new Meteor.Collection("workflow");
After creating project, I am selecting project in the form and displaying Work flow card.
HTML:
<!-- Workflow Card -->
<div id="wCard">
{{#each workflow}}
**<div class="pheader">
<h2>{{project}}</h2>
<hr width="100%">
</div>**
<br>
<div class="workflowcard">
<div class="module-card">
<div class="card-header wfmodule">{{workflowTitle}}</div>
<div class="casting">
<div class="assigned-tag">Assigned To:</div>
<div class="assigned-to">{{team}}<hr></div>
<div class="actions">No Actions Created</div>
</div>
<div class="due">
Due on:
<div>
<div class="day-stamp" >{{weekday d_date}}</div>
<div class="date-stamp">{{date d_date}}</div>
<div class="month-stamp">{{month d_date}}</div>
</div>
</div>
</div>
<div class="btn-box showmuloption">
<button type="edit" class="editw" style="display:none">Edit Workflow</button>
<button type="hide" class="hidew" style="display:none">Hide Actions</button>
<div class="actionBtn"><button class="btn-wf stage-blue-wf button-x-small-wf" id="newAction">New Action</button></div>
</div>
</div>
{{/each}}
</div>
.JS:
Template.workflow.helpers({
getWorkflow: function(){
return Workflow.find();
},
user: function(){
return Meteor.users.find({});
},
getNewaction: function(){
return Newaction.find();
},
});
Now the workflow cards are displaying in a list. I want to display workflows according to projects. If I select a project, the workflow should go to that project, and I create another workflow with same project, it should display in that project. And if I select another project, the workflow should display in that related project.
Please help through this.
I use reactive varrible for this.
At first you need add meteor package:
$ meteor add reactive-var
Your form with project selecting might look like this:
<select id="project" value="{{getProject}}">
{{#each getProjectsList}}
<option id='{{_id}}' value="{{_id}}">{{projectname}}</option>
{{/each}}
</select>
Don't forget create helpers getProject and getProjectsList.
Now it's time for reactive varrible, you can initialise this in onCreated event.
Template.workflow.onCreated(function() {
var instance = this;
instance.projectId = new ReactiveVar(null);
});
When you change selected project, you should change you reactive varrible.
Template.workflow.events({
'change #project': function(){
Template.instance().projectId.set($("#project").val());
});
Every workflow need to have field with project id. You get workflows list like this
{{#each getWorkflows}}
And there is helper for getting workflow's list:
Template.workflow.helpers({
getWorkflows: function() {
var id = Template.instance().projectId.get();
return Workflow.find({projectId: id});
},
...// another helpers
})
So, when you will change project in form, list of workflow also will change, because it depends on reactive var. Also you can sibscribe only needed workflow object, and not all collection.
I hope this will helpfull to someone.

Why is #first always false in my handlebars #each loop?

Using Ember.Handlebars, I'm trying to set up a Bootstrap carousel to showcase a selection of issues from my data store.
I want to add the active class on the first item of my carousel, but it sounds like my {{if #first}} test is never evaluated true.
My app/templates/issues-list.hbs is :
<div id="showcase-issues" class="carousel slide">
<div class="carousel-inner">
{{#each model.issues as |issue|}}
{{#if #first}}
<div class="active item">
{{#issue-item issue=issue}}{{body}}{{/issue-item}}
</div>
{{else}}
<div class="item">
{{#issue-item issue=issue}}{{body}}{{/issue-item}}
</div>
{{/if}}
{{/each}}
</div>
{{!-- Nav buttons, etc. ... --}}
</div>
My app/routes/issues-list.js is simply :
model: function() {
var issues = this.get('store').filter('issue', {
filters: { "state" : "visible" }
}, function(item) {
return (item.get('state') === "visible") ;
}).then( function(results) {
return results ;
}) ;
return Ember.RSVP.hash({issues: issues}) ;
}
Did anyone already face this problem ?
Is there a proper way to handle DS.FilteredRecordArrays in a {{#each ...}} helper ?
I'm working with :
Ember 1.13.2
Ember-data 1.13.5
Bootstrap 3.3.5
Thanks a lot for any given hand !
#index and #first isn't available in htmlbars. You can however:
{{#each model.issues as |issue index|}}
<div class="item {{unless index 'active'}}">
{{#issue-item issue=issue}}{{body}}{{/issue-item}}
</div>
{{/each}}
See: http://jsbin.com/zupezap/2/edit?html,css,js,output

Meteor Template.myTemplate.helpers not rendering output

I am new to meteor and i am wondering why is it myTemplate.helper is not rendering its supposed output when i started putting these files in my /client/template directory. These are the following files:
/clinent/template/body.html:
<body>
<div class="row">
<div class="col-xs-12">
<div class="list-group">
{{#each projects}}
{{> projectList}}
{{/each}}
</div>
</div>
</div>
</body>
/client/template/body.js:
Project = new Mongo.Collection("project");
if (Meteor.isClient) {
Template.body.helpers({
projects: function(){
var projects = Project.find({});
return projects;
}
});
};
/client/template/templates.html:
<template name="projectList">
<a href="#" id="{{id}}" class="list-group-item {{#if active}} active {{/if}}">
{{name}}
<i class="glyphicon glyphicon-trash pull-right del"></i>
</a>
</template>
However it is rendering the ouptut properly when i put body.html and body.js at the root / directory.
I think I know what the problem is.
Project = new Mongo.Collection("project");
Should be available to both client and server, when you move body.js to client folder it is automatically served only to client, and it breaks the app.
Try following structure:
/client/template/body.js:
Template.body.helpers({
projects: function(){
var projects = Project.find({});
return projects;
}
});
/collections.js
Project = new Mongo.Collection("project");
Note that you don't need if(Meteor.isClient) when creating files inside client folder.
I think it will work if you use
Template.projectList.helpers
instead of
Template.body.helpers
When the helper is for a template then you have to put the template name and not body.

Meteor, How do I change a template (view) on event?

I'm building an app with two views: home & view list
When the user clicks on a list's name on the home view, it should change to the "view list" template. I've added a session variable called 'view', setting it to 'home' on startup. When a click event is detected on one of the items (list name) on the home screen, it changes the value of view to 'viewList'. Then in the HTML, I have an if statement to show the home template if 'view' is 'home', otherwise show the 'viewList' template.
I can tell the first part works because I'm outputting the value of 'view' and it does output the value "viewList" when you click on a list name, it just doesn't change the template.
What am I missing?
My code:
mylists.js:
Lists = new Mongo.Collection("lists");
if (Meteor.isClient) {
Meteor.startup( function() {
Session.set("view", "home");
});
Template.main.helpers({
view: function () {
return Session.get("view");
}
});
Template.home.helpers({
lists: function () {
return Lists.find({}, {sort: {lastUsed: -1}});
}
});
Template.home.events({
"submit #new-list": function (event) {
var name = event.target.listName.value;
Lists.insert ({
name: name,
createdAt: new Date(),
lastUsed: new Date()
});
},
"click .list-row": function (event) {
Session.set("view", "viewList");
}
});
}
mylists.html:
<head>
<title>My Lists</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{view}}
{{#if view "home"}}
{{> home}}
{{else}}
{{> viewList}}
{{/if}}
</template>
<template name="home">
<header>
<h2>My Lists</h2>
</header>
<ul id="lists">
<li>
<form id="new-list">
<input type="text" name="listName" value="My List 1">
<input type="submit" value="Save">
</form>
</li>
{{#each lists}}
{{> list}}
{{/each}}
</ul>
</template>
<template name="viewList">
<header>
<h2>View List</h2>
</header>
<!-- list details will show here -->
</template>
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
</template>
If you want to change from templates view i suggest you tu install the iron:router package.
run
meteor add iron:router
lester create the routes.js on the /lib folder
now lets do this step by step.
First create 1 template on myAppName/client/views/layout.html
<template name="layout">
{{> yield}}
</template>
and update the routes.js with this code.
Router.configure({
layoutTemplate: 'layout' // here we say that layout template will be our main layout
});
Now on the same routes.js create this 2 routes.
Router.route('/home', function () {
this.render('home');
});
Router.route('/viewList', function () {
this.render('viewList');
});
With this if you navigate to localhost:3000/home or /viewList you will see the html content on there.
NOTES: <header> inside the templates you don't need it.
Now this is just an example because i don't really know whats your main idea here.
you are calling {{#each lists}} inside the home template, so whats the point of having the viewList template?
Now if you want to create individual and dynamic routes for each list you can try this.
Router.map(function () {
this.route('listViews', {
path: '/listViews/:_id',
waitOn: function(){
return Meteor.subscribe('lists')
},
data: function(){
return Lists.findOne({_id: this.params._id});
}
});
});
Now with this, you have dynamic templates for each object on the List collection, if you go to localhost:300/listView/35dwq358ew for example you will get render the listView with some data.
you can do stuff like this inside the template list
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
<li>Check this List in detail</li>
</template>
and the viewList template will look like this.
<template name="viewList">
<h2>{{title}}</h2>
<!-- list details will show here -->
{{informationAboutList}}
</template>

Sending data into a nested Controller/View in EmberJS

I'm messing around with JSON structures in EmberJS starting from the top level Application level and trying to pass data to a general MenuController/MenuView child so I can reuse it.
The JSON I've come up with to play around with how data gets passed through nested ember structures is this:
JSON
{
appName: "CheesyPuffs"
menuItems: [
{name:"Gouda"}
{name:"Crackers", menuItems: [
{name: "Cheezeits"}
]
}
]
}
Handlebars
<script type="text/x-handlebars">
<div class='app'>
<div class='header'>
{{#if menuItems}}
// Embed template 'menu'
{{/if}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="menu">
<ul>
{{#each menuItems}}
<li>{{name}}</li>
{{#if menuItems}}
// Embed menu template
{{/if}}
{{/each}}
</ul>
</script>
JS
App.MenuController = Ember.ArrayController.extend({
actions: {
click: function(){
// Signal Event to App
}
}
});
App.MenuView = Ember.View.extend({
click: function(){
console.log("I clicked a menu");
}
});
All the examples I've seen concerning nested stuff involves routes with the classic _id subroute. I'm not sure how I would go about telling the App Router that it needs to pass the menuItems data to a child controller that's embedded in the same view. I have a feeling you can do this both via the template and programmically? If so, how would you do it both ways?
using the template you should use render. And that's the way you should do it, programmatically doesn't make sense.
<script type="text/x-handlebars">
<div class='app'>
<div class='header'>
{{#if menuItems}}
{{render 'menu' menuItems}}
{{/if}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="menu">
<ul>
{{#each menuItems}}
<li>{{name}}</li>
{{#if menuItems}}
{{render 'menu' menuItems}}
{{/if}}
{{/each}}
</ul>
</script>

Categories

Resources