This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 7 years ago.
I have two collections:
Group = {
users: [Array_of_User]
}
User = {
name: _string_
}
I'm listing groups ans I'm trying to know in the template if a user is in the groups:
mytemplate.js
Template.mytemplate.helpers({
groups: function(){
return Groups.find();
},
currentUsername: 'test'
});
mytemplate.html
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if [the group contains currentUsername] }}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>
The question is: what can I put on the helpers and instead of [the group contains currentUsername] to make it work?
Also, I'm not saying this is the way to do it. I'm open to any suggestions even if it means I have to change a lot.
You could use the Underscore.js function _.findWhere(list, properties) to check whether the group contains the username:
if (Meteor.isClient) {
Template.main.helpers({
groups: function() {
return Groups.find();
},
currentUsername: 'Matthias',
isInGroup: function(username) {
return !!_.findWhere(this.users, {
name: username
});
}
});
}
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if isInGroup currentUsername}}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>
if (Meteor.isServer) {
Meteor.startup(function() {
Groups.insert({
users: [{
name: "Matthias"
}, {
name: "Angie"
}]
});
});
}
Here is a MeteorPad.
Within your each block, your data context becomes the current group that is being iterated over. Therefore you can write a helper method that references that current data context like this:
userInGroup: function(username) {
var userInGroup;
this.forEach(function(groupUsername) {
if (username == groupUsername) {
userInGroup = true;
}
};
return userInGroup;
}
'this' within the userInGroup template helper references the current group as long as you use the helper within an a group iteration.
You can then use the helper like this:
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if userInGroup currentUsername}}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>
Related
I am following an ember-rails tutorial. It's using coffeescript and I'm writing in javascript. Essentially I have a form that when I submit text on it it should place the text below.
My controller looks like this:
Emberapp.ApplicationController = Ember.Controller.extend({
entries: [],
actions: {
addEntry: function(){
this.entries.pushObject name: this.get('newEntryName');
this.set('newEntryName', "");
}
}
});
My template looks like this
<div id = "container">
<h1>Emberails</h1>
{{ input value=newEntryName enter='addEntry' }}
<ul>
{{#each entries}}
<li>{{name}}</li>
{{/each}}
</ul>
</div>
When I reload the page I get an error stating that 'name: this.get('newEntryName');' is an Unexpected identifier. I've been checking for the syntax rules online but I'm not sure if it is a coffeescript to javascript error or something else.
this.entries.pushObject name: this.get('newEntryName');`
is not valid JS. You want do do
this.entries.pushObject({name: this.get('newEntryName')});
Controller,
Emberapp.ApplicationController = Ember.Controller.extend({
newEntryName: '',
entries: [],
actions: {
addEntry: function(){
this.get('entries').pushObject({name: this.get('newEntryName')});
this.set('newEntryName', "");
}
}
});
in hbs,
<div id = "container">
<h1>Emberails</h1>
{{ input value=newEntryName enter='addEntry' }}
<ul>
{{#each entries as |value|}}
<li>{{value.name}}</li>
{{/each}}
</ul>
</div>
Like Lux suggested consider ember-cli and read http://guides.emberjs.com
I have a custom user field that get populated by the user on click of a button with an id of an item from another collection, however when i return it, i get a single list of the items in one html tag, instead of returning each saved item in its own tag with the result looking like this
i.e its like this
<p>CategoryPublication-98,CategoryPublication-2,CategoryPublication-57<p>
when it should be like this
<p>CategoryPublication-98</p>
<p>CategoryPublication-2</p>
<p>CategoryPublication-57</p>
this is my publish
Meteor.publish(null, function() {
return Meteor.users.find({_id:{$in:fields.name}}).fetch();
});
my html
<template name="userTimeline">
{{#if currentUser}}
<div class="timeline-user">
{{#each name}}
<p>{{name}}</p>
{{/each}}
</div>
{{/if}}
</template>
my helper
Template.userTimeline.helpers({
name: function() {
return Meteor.user().name;
}
});
my insert
Template.CategoriesMain.events({
'click .toggle-category': function(e){
var ob = this._id;
var id = $.makeArray( ob );
console.log(id);
e.preventDefault();
Meteor.call('addingCategory', id, function(error, user){ console.log(id)});
},
});
My methods
Meteor.methods({
addingCategory: function(name) {
console.log(Meteor.userId());
Meteor.users.update({
_id: Meteor.userId()
},
{
$addToSet: {
name: name
}
});
}
});
Where you have:
{{#each name}}
<p>{{name}}</p>
{{/each}}
There's ambiguity about the value of name in the inner <p></p>. Since you're just returning an array of strings instead of objects there is no name key in the array.
Instead do:
{{#each name}}
<p>{{this}}</p>
{{/each}}
I try to integrate rubaxa:sortable to make my list sortable.
client/helpers.js
Template.getElements.helpers({
children: function() {
return Articles.find({ parent: this._id }, {sort: {order: 1}});
}
});
server/publications.js
Meteor.publish('articles', function() { return Articles.find({}, {sort: {slug: 1}}); });
Sortable.collections = 'articles';
template
<template name="getElements">
<ul class="sortable">
{{#each children}}
{{#sortable items=Articles sortField="order"}}
<li data-id="{{_id}}"><input type="text" name="keyword" value="{{title}}"></li>
{{/sortable}}
{{/each}}
</ul>
</template>
In the documentation (https://atmospherejs.com/rubaxa/sortable) I see the info:
Client:
{{#sortable items=<collection|cursor|array> sortField="order"}}
Server:
Sortable.collections = <collectionName>; // the name, not the variable
So what am I doing wrong? Right now no list-element is beeing shown.
I'm not an expert but based on integration this will fix your issues.
Server JS
Update the declaration to include the collation name in [].
Sortable.collections = ['articles'];
HTML Template
remove the following:
{{#each children}}
{{/each}}
Regards,
Vince
In this Example 2 -- "Passing a data context"
JS
Template.overview.helpers({
users: [
{ name: 'David' },
{ name: 'Shaune' }
]
});
HTML
<template name="overview">
{{> userList users}}
</template>
<template name="userList">
{{#each this}}
{{name}}<br>
{{/each}}
</template>
Result
David
Shaune
My goal is to pass an array of template names into Template.overview where users is, like so:
<template name="overview">
{{#each templateArray }}
{{> userList this }}
{{/each}}
</template>
Where templateArray is an array of strings with template names, and this is the name of each template.
Is this possible?
EDIT:
For more depth, consider that I have the following in my helpers
Template.overview.helpers({
users: [
{ name: 'David' },
{ name: 'Shaune' }
],
otherUsers: [
{ name: 'Jane' },
{ name: 'Betty' }
],
moarUsers: [
{ name: 'Ben' },
{ name: 'Jerry' }
]
});
And I'd like to pass each of these data context into the same template (in this case userLists).
You don't need to call anything, you can use this inside helper, like
helper: function(){
return this; //if you pass string via templateArray
return this.name; //if you pass object via templateArray
}
Because what you do looks like this but is just wrapped nicely into templates
<template name="overview">
{{#each templateArray }}
{{name}}<br>
{{/each}}
</template>
I don't know why you have in code double loop, in first loop you pass object and it can't iterate throught it
EDIT
If you wanna just loop throught array of strings, do:
{{#each templateArray}}
{{this}}<br>
{{/each}}
Lets say I have the following JSON and handlebars.js template :
JSON
{
rootPath: '/some/path/',
items:[ {
title: 'Hello World',
href: 'hello-world'
}, {
title: 'About',
href: 'about'
}, {
title: 'Latest News',
href: 'latest-news'
}
}
Template
<script id="test-template" type="text/x-handlebars-template">
<ul class="nav">
{{#each items}}
<li>{{title}}</li>
{{/each}}
</ul>
</script>
The template above works, until I want to filter items - lets say to have 2 lists one odd and the other even, here's a simple template for odd :
<script id="test-template" type="text/x-handlebars-template">
<ul class="nav">
{{#each items}}
{{#isOdd #index}}
<li>{{title}}</li>
{{/isOdd}}
{{/each}}
</ul>
</script>
And the registered helper :
// isOdd, helper to identify Odd items
Handlebars.registerHelper('isOdd', function (rawValue, options) {
if (+rawValue % 2) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
The helpers work as expected and only the Odd items are rendered, however the reference to the parent context becomes lost, so the {{../rootPath}} directive ~~fails to render~~ renders an empty value.
Is there a way to pass the Parent context through the block Helper?
Change this:
<a href="{{../rootPath}}{{href}}">
to this:
<a href="{{../../rootPath}}{{href}}">
Why? because the if statement is in an inner context so first you need to go up a level and that's why you have to add ../
See more details in:
https://github.com/wycats/handlebars.js/issues/196