Using #key in a path in handlebars - handlebars.js

lets say i have this data
{
method: ['twitter','reddit','google'],
auth: {
twitter: {id: 213},
reddit: {},
}
}
i want to list all the methods that are not in auth, or are in auth but dont have an id listed
methods in auth with id:
{{#each auth}}
{{#if id}}
{{#key}}
{{/if}}
{{/each}}
methods not in auth with id:
{{#each method}}
{{#unless (lookup ../auth this)}}
{{this}}
{{/unless}}
{{/each}}
What I'm hoping to see is the first part printing out just twitter (since it's the only one that's in auth and has an id), and in the second part it should print out the opposite, both reddit and google.
Right now the second part only prints out google
My current code works for things that aren't in the auth object (google), but it's not able to check if there's an ID defined in the auth object, so it doesn't print out reddit even though it should.
I tried doing {{#unless (lookup ../auth this.id)}} but that prints out all 3, presumably because the lookup is failing.
here's a codepen: https://codepen.io/skeddles/pen/bGjzRZx

I think you are on the right track. I would just add a second lookup:
{{#each method}}
{{#unless (lookup (lookup ../auth this) 'id')}}
{{this}}
{{/unless}}
{{/each}}
This takes the result of lookup ../auth this and looks for an id property on that result. Therefore, only methods that have keys in auth that resolve to an object with id property will resolve as truthy.
I have forked your Codepen.

Related

Accessing an element within a list of Json objects using handlebars.js

"guests": [
{
"guestname": "john smith",
"is_active": false,
"guestheight": "175cm",
"guestprofile": "https://www.example.com"
},
{
"guestname": "david smart",
"is_active": false,
"guestheight": "175cm"
}
]
I would like to check if guestprofile exist. Given that I currently have a variable holding the index of the list we are trying to access here, namely itemIndex. So basically I'm trying to query if guests[itemIndex]["guestprofile"] in handlebars.js context.
If I make a direct reference like
{{#if guests.0.guestprofile}}
//do something
{{/if}}
its working fine. However, if I replace 0 with itemIndex like below, everything broke...
{{#if guests.itemIndex.guestprofile}}
//do something
{{/if}}
Currently I have also tried
{{#if (lookup guests itemIndex).guestprofile}}
//do something
{{/if}}
{{#if guests[itemIndex].guestprofile }}
//do something
{{/if}}
None of them actually worked. Please help, Thank you in advance!
You were so close with your lookup attempt.
The issue is that Handlebars does not allow you to chain a key onto a lookup subexpression as you are doing with (lookup guests itemIndex).guestprofile. It just doesn't resolve dynamic variables that way, which is the same reason why lookup has to be used instead of guests.itemIndex.guestprofile.
The part you missed is that you actually need two lookups - one to get the element of guests at itemIndex and the second to get the guestprofile of that element.
Your template needs to become:
{{#if (lookup (lookup guests itemIndex) 'guestprofile')}}
do something
{{/if}}
I have created a fiddle for your reference.

Meteor Blaze display array

I have collections like this:
I want to iterate over object.questions.teema for example.
I have helper:
Template.game.helpers({
theGame: function() {
var theGame = Game.findOne({_id:"LhQmaZKW8eJNenyX9"})
console.log(theGame)
return theGame
}
});
and template:
<template name="game">
{{#with theGame}}
{{#each theGame.questions}}
{{teema}}
{{/each}}
{{/with}}
</template>
But it doesnt work, what is wrong with the template?
'#each theGame.questions' Will not work inside the #with, because you can access the 'theGame' object directly.
The point is when you try to get theGame object inside the #with it will return you undefined, because 'theGame' object does not have theGame property, Which you want to access inside #with block.
<template name="game">
{{#with theGame}}
{{#each questions}}
//Thie #each because you have nested array. As I can see in your console log.
{{#each this}}
{{teema}}
{{/each}}
{{/each}}
{{/with}}
</template>
What is {{teema}} supposed to be?
Regardless, as you can see from your console.log statement, {{theGame.questions}} returns another array. But that array returns objects. This is really hard to query for with Blaze.
The better solution would be to flatten it out so that your data is shaped like this:
questions: [
{
a: 'asdfkjah',
level: 'askdjfhal',
q: 'asdkfh',
teema: 'asdkfjh'
vaartus: 100
},
{
...
}
]
This way you don't have an array nested in an array. That will allow you to:
{{#with theGame}}
{{#each theGame.questions}}
{{this.teema}}
{{/each}}
{{/with}}
theGame.questions is an array (that you iterate over) of array of objects which have the teema key. So you still need to iterate over the 2nd level array, or define a specific item in that array before you can eventually reach the object with teema property.
Maybe something like:
{{#with theGame}}
{{#each questions}}
{{#each this}}
{{this.teema}}
{{/each}}
{{/each}}
{{/with}}
But it depends on why you have these 2-level arrays in the first place.

With clause changes keypath

I have the following template:
{{#each Posts}}
{{#with { Post: this } }}
<h2 on-click="doSomething">{{Title}}</h2>
...
{{/with}}
{{/each}}
When I click on the header and doSomething get called, I get "${{Post:Posts-0}}" in event keypath. But I need to get access to the post keypath: "Posts.0" to modify some of its properties. What is the right way to achieve that?
Using a {{#with { a: b } }} block for aliasing in Ractive has some limitations, as it's not true aliasing, it's simply creating an expression with an object literal. It's a needed enhancement to offer true aliasing with something like {{#each Post in Posts}} or {{#each Posts as Post}}.
As far as what you can do today, you can add the keypath to the with block:
{{#with { Post: this, keypath: #keypath } }}
And then either pass in:
<h2 on-click="doSomething:{{keypath}}">{{Title}}</h2>
Or access in the event via this.event.context.keypath. See http://jsfiddle.net/w0npbnrz/ for both of these in action.
You also could use {{#each Posts:p}} in which case you could get the keypath via 'Posts.' + this.event.index.p.

How to display Meteor.user() profile data in the view

I imagine this has to be an elementary issue however I've been struggling through this for too long. I'm relatively new to Meteor.
I've viewed the documentation for the Meteor.user() (http://docs.meteor.com/#meteor_users) and can see how additional information is added to the user.profile. I.e.,
//JS file
Meteor.users.insert({
username: 'admin',
profile: {
first_name: 'Clark',
last_name: 'Kent'
},
});
How then do I display the profile information in the view template? I can access the user object via the view and web console (Meteor.user()) however I cannot access the object details.
My initial thoughts were that I could load the following in my handlebar templates but they do not work:
// HTML view
{{Meteor.user().username}}
{{Meteor.user().profile.first_name}}
{{Meteor.user().profile.last_name}}
Any help is greatly appreciated.
Your insert is correct.
But to show the information like the first name you have to provide a helper function.
Your html-template:
<template name="user">
<p>{{firstName}}</p>
</template>
Your js-code:
Template.user.helpers({
firstName: function() {
return Meteor.user().profile.first_name;
}
});
You can additionaly wrap the user template with the {{currentUser}} helper to be sure there is a user.
{{#if currentUser}}
{{> user}}
{{/if}}
If you don't want to define a proxy helper for different attributes of objects nested in {{currentUser}}, you can do the following purely in your template:
{{#with currentUser}}
{{#with profile}}
{{first_name}}
{{/with}}
{{/with}}
Updated to reflect comment suggestion.
In your templates, you'll want to use {{currentUser}} instead of {{Meteor.user()}}.
Docs
try this way
{{#with userDetails}}
First name:-{{this.first_name}}
Last name:- {{this.last_name}}
{{/with}}
//jsSide
userDetails(){
return Meteor.user();
}

How to access outer {{#each}} collection value in the nested loop

What is the standard way to access outer #each collection values in the loop?
for example:
<template name="example">
{{#each outerCollection}}
<tr>
{{#each innerCollection}}
<td>{{aaa}}</td>
{{/each}}
</tr>
{{/each}}
</template>
Template.example.aaa = function(){
// cannot access outerCollection values
}
in above Template.example.aaa, this points to the inner collection.
I cannot find way to access outerCollection items.
My solution is like below, I am defining my own helper function.
Is it a standard Meteor way to achieve this purpose?
<template name="example">
{{#each outerCollection}}
<tr>
{{#each innerCollection}}
<td>{{myHelper ../outerItem innerItem}}</td>
{{/each}}
</tr>
{{/each}}
</template>
Handlebars.registerHelper('myHelper', function (outItem, inItem) {
// can access outerCollection via outerItem
});
I found a similar question for the case of inner event handler access.
I think you've answered this yourself! Using ../ is documented in https://github.com/meteor/meteor/wiki/Handlebars.
You can use below code to fetch outer collections.
suppose you have collection called as Collection.Customer and Collection.RechargePlan and you are using both in a template for updating Customer.
Customer = {"name":"James", "rechargeplan":"monthly"};
RechargePlan = [{"rechargeplan": "monthly"},{"rechargeplan": "yearly"}];
//Inside template, Bydefault Customer is available.
{{#each RechargePlan}}
{{#if equals ../rechargeplan rechargeplan}}
//Hurray Plan matches
{{/if}}
{{/each}}
In above code, ../rechargeplan is actually Customer.rechargeplan, ../ actually went one step above heirarchy and then accessed the field if available, since Customer is already available to template, it's field is picked up.

Resources