Ember.js using each, get count - javascript

Using Ember.js with handlebars, and looping through results like:
{{#each transaction in transactions }}
<p>Transaction: {{ transaction.name }}</p>
{{else}}
<p>No results...</p>
How can I look at the total count of transactions and if greater than 10, add a simple load more:
<p><a {{action loadMoreResults}}>Load more transactions...</a></p>

Implement a custom handlebar helper, something like if_gt
{{#if_gt transactions.length compare="10"}}
<p><a {{action loadMoreResults}}>Load more transactions...</a></p>
{{/if_gt}}
And your Helper will be defined something like this
Handlebars.registerHelper('if_gt', function(context, options) {
if (context > options.hash.compare)
return options.fn(this);
return options.inverse(this);
});
In that case you can try this.. just move the element to outside the loop
{{#if something}}
{{#each transaction in transactions }}
<p>Transaction: {{ transaction.name }}</p>
{{/each}}
{{else}}
<p>No results...</p>
{{/if}}
{{#if_gt total_transactions compare="10"}}
<p>Load more...</p>
{{/if_gt}}

Related

Checking equality in Blaze?

The user can only delete a post if he was the one who posted it.However a user can see all the posts.The javascript code is:
var postedBy = Meteor.user();
var currentPost = this._id;
Posts.insert({
name:postName,
createdAt:new Date(),
postId:currentPost,
postedBy:postedBy
});
The HTML code is:
<template name="posts">
{{#if currentUser}}
{{> addPost}}
<ul>
{{#each post}}
<li>{{> postItem}}</li>
{{/each}}
</ul>
{{/if}}
</template>
<template name="postItem">
<li>
<h4>{{name}}</h4>
<i>Posted by {{postedBy.username}} on {{createdAt}}</i>
[Delete]
</li>
</template>
<template name='addPost'>
<input type='text' placeholder='Add post here' name='postName' id ='myinput'>
<button class="btn btn" type="button" id='btn'>Post</button>
</template>
Both currentUser.username and postedBy.username are displaying the names of the logged in user and the user who posted a particular post respectively.
I am trying to work with the Delete anchor tag.
{{#if currentUser.username==postedBy.username}}
[Delete]
{{/if}}
But it shows error in command prompt.I know it is wrong but I can't think of any other way.How do i write this 'if' statement to check if the current user was the one who posted this post?
Please help as I am new to Meteor.Sorry for bad English.
You can't use arbitrary JavaScript expressions in spacebars. Add a helper like this:
Template.postItem.helpers({
canDelete: function (){
return Meteor.user().username === this.postedBy.username;
}
});
Which you can then use in your template like this:
{{#if canDelete}}
Delete
{{/if}}
Also note, instead of copying the user object into each post, the recommended way is to store the user's id in postedBy.

How to know if an insertion was successfull in a MongoDB Collection with Meteor.JS (inside the Template)

The situation
Let's break this question down to a simple todo list of which the entries are listed in a \li:
//main.html
<ul>
{{ #each listEntries }}
<li class="item">
{{ title }}
</li>
{{ /each }}
</ul>
Serverside:
//main.js
TodoCollection = new Mongo.Collection('todo_collection');
Now I am calling manually from the console in the client:
TodoCollection.insert({title: 'My first entry'});
Up to this point everything's fine.
Now meteor.JS works asynchronously which means that the changes that are made in the client also have effect on the DOM right away without knowing if the database insertion was successfull or not. If not, the DOM Element will be removed again (so first meteor inserts the new <li>, then it removes it again if insertion failed).
How can you get the information from meteor that something comes actually from the database?
What I need:
//main.html
<ul>
{{ #each listEntries }}
<li class="item">
{{ title }}
{{ #if isInDatabase }}
- i am actually stored!
{{ /if }}
</li>
{{ /each }}
</ul>
You can use the callback of the insert method of the collection. The callback is called with the error (null if there is none) and the object Id that was stored in the database
Below you can see the code to test this:
html:
<head>
<title>simple</title>
</head>
<body>
<h1>Welcome to Meteor!</h1>
{{>test}}
</body>
<template name="test">
<ul>
{{#each item in list}}
<li>{{item.name}}</li>
{{/each}}
</ul>
{{#if insertResult}}
<div class="insert_result">{{insertResult}}</div>
{{/if}}
{{#if insertError}}
<div class="insert_error">{{insertError}}</div>
{{/if}}
<form>
<input type="text" name="name" />
<input type="submit" value="Add" />
</form>
</template>
Javascript:
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
collection = new Mongo.Collection('collection');
if (Meteor.isClient) {
Template.test.onCreated(function () {
this.insertResult = new ReactiveVar();
this.insertError = new ReactiveVar();
});
Template.test.helpers({
list() {
return collection.find();
},
insertResult() {
return Template.instance().insertResult.get();
},
});
Template.test.events({
'submit form'(event, instance) {
event.preventDefault();
collection.insert({
name: event.target.name.value
},function(err,result) {
if (err) {
instance.insertError.set(err);
instance.insertResult.set(null);
} else {
instance.insertResult.set(result);
instance.insertError.set(null);
}
});
},
});
}
As you can see in the previous answer, it is quite cumbersome in Meteor to know what causes a reactive update.
I would suggest a different approach: Don't insert on the client. Make a Meteor.call() to a server method which does the insert, and then let the client update reactively. Then you are always sure that what you see on the screen is actually in the database.
I think I found the most trivial solution myself:
Adding a hook on server-side that will add the date of creation with obj.onCreated = new Date(); helps identifying that it came from the server because this will not exist on the client.
{{#each item}}
{{ #if item.onCreated }}
<li class="success-db">{{name}}</li>
{{ else }}
<li class="pending-db">{{name}}</li>
{{ /if }}
{{/each}}
(Please do not hesitate to improve this answer if you find it contradictory to how Meteor.JS works)
If you want to show the data which title exist then you can write the code like this.
<ul>
{{ #each listEntries }}
<li class="item">
{{ title }}
{{ #if title }}
- i am actually stored!
{{ /if }}
</li>
{{ /each }}
</ul>

Ractive binding to parent

I have a simple template for posts with comments:
{{#each Posts}}
{{Text}}
{{#each Comments}}
//how can I bind to Post.Id here? Like {{../Id}}
{{/each}}
{{/each}}
How can I bind to a parent #each block (I need to get post's Id property) inside comments #each block?
Ractive supports Restricted References, so just like you have it:
{{#each Posts}}
{{Text}}
{{#each Comments}}
Post Id: {{../../Id}}
Comment Id: {{Id}}
{{/each}}
{{/each}}
You can also alias Parent fields if you don't need bidirectional updates on the aliased field:
{{#each Posts}}
{{Text}}
{{#with { PostId: Id } }}
{{#each Comments}}
Post Id: {{PostId}}
Comment Id: {{Id}}
{{/each}}
{{/with}}
{{/each}}

How Do I Return Template From Meteor Template Helper?

My HTML:
<template name="foo">
{{#each category}}
{{#if this.custom}}
{{> someTemplateName}}
{{else}}
{{> generic}}
{{/if}}
{{/each}}
</template
How do I return some value to `someTemplateName' so that I can switch templates based on on the object in the #each statement.
Template.foo.someTemplateName = function () {
return A_TEMPLATE_NAME
}
Thanks.
The correct syntax is the following :
JS
Template.foo.helpers({
someTemplate:function () {
return Template.someTemplate;
}
});
HTML
<template name="someTemplate">
<p>SOME TEMPLATE</p>
</template>
It is not really the name that you manipulate but template objects which live under the variable name Template.myTemplate.
If you want to manipulate template names, try UI.dynamic :
HTML
<template name="foo">
{{> UI.dynamic template=someTemplateName}}
</template>
JS
Template.foo.helpers({
someTemplateName:function () {
return "someTemplate";
}
});
The solution was actually very simple.
<template name="foo">
{{#each category}}
{{#if this.custom}}
{{> someTemplateName}}
{{else}}
{{> generic}}
{{/if}}
{{/each}}
</template>
And I return a helper:
Template.foo.someTemplateName = function () {
return Template[this.name];
}
Where this.name is from the `{{#each}}' context.

Handlebars parse error on #each

I'm returning the following JSON object
{"status":"success",
"valmessage":"Your message has been sent successfully.",
"postcontent":{
"post_author":1,
"post_recipient":"1",
"post_title":"handle test 2",
"post_type":"wp_inbox_msg",
"post_content":"<p>giving it another go.<\/p>\n"},
"postmeta":{
"postid":410,
"postdate":"Monday, March 17th, 2014",
"author":"admin"},"replies":null,
"Formerrors":[]
}
and I'm getting the following error inside my handlebars template :
Uncaught Error: Parse error on line 23:
...replies}} {{ #each replies }
----------------------^
Expecting 'ID', 'DATA', got 'INVALID'
inside my tempalte I'm doing the following :
{{#if replies}}
{{ #each replies }}
<li>
<figure class="reply-author-img">
<img alt="" src="{{ avatar }}" height="96" width="96">
</figure>
<div class="replycontentwrap">
<div class="reply-from">
<p class="reply-author">
<strong>{{ fullname }}</strong>
<span>{{ nickname }}</span>
</p>
<span class="replydate">{{ reply_date }}</span>
</div>
<div class="reply-content">{{ reply_content }}</div>
</div>
</li>
{{ /each }}
{{/if}}
Replies is currently Null but it should be returning a set of objects when there are replies to the message, How would be the best way to 1) get this working and 2) approach this kind of data structure with handlebars.js ?
The error you are getting is a result of the fact that you have a space before the '#each' and '/each', so make it:
{{#each replies}}
/* each stuff */
{{/each}}
You can also directly use as below to reduce complexity, also you get good understanding if there are multiple each blocks.
{{#replies}}
{{this}}
{{/replies}}
This method is parallel to #each and can iterate key value if it is object, otherwise array index and object(value)

Categories

Resources