I have a user index and would like to display information on each user. User ID shows up fine, but the app isn't showing emails.
Here is my template:
<template name="users">
<h1>List of all users</h1>
{{#each users}}
<div class="list_item">
<p>ID: {{_id}}</p>
<p>Email: {{email}}</p>
</div>
{{/each}}
</template>
And here are my routes:
Router.route('/users', function () {
this.render('users');
}, {
waitOn: function() {
return [
Meteor.subscribe('users')
]
},
data: {users: Meteor.users.find({})}
});
And finally, my publication:
Meteor.publish('users', function () {
return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});
});
Any ideas?
The correct way to display the email would be :
<p>Email: {{emails.[0].address}}</p>
Email addresses are stored as an array in the user object.
You can check by typing Meteor.user() in the console :
Object {
...
emails: Array[1]
0: Object{
address: "username#domain.com",
verified: false
}
...
}
{{ currentUser.emails.[0].address }}
Related
I am working through this Meteor tutorial and I have updated imports/ui/task.html to only show the tasks to the user who created them as follows:
<template name="task">
{{#if isOwner}}
<li class="{{#if checked}}checked{{/if}} {{#if private}}private{{/if}}">
<button class="delete">×</button>
<input type="checkbox" checked="{{checked}}" class="toggle-checked" />
<span class="text">{{text}}</span>
</li>
{{/if}}
</template>
However, I still have the incomplete count showing tasks by all users and I want to change it to just the user who is logged in. This is the part of imports/ui/body.js that I think needs to be changed.
Template.body.helpers({
tasks() {
const instance = Template.instance();
if (instance.state.get('hideCompleted')) {
// If hide completed is checked, filter tasks
return Tasks.find({ checked: { $ne: true } }, { sort: { createdAt: -1 } });
}
// Otherwise, return all of the tasks
// Show newest tasks at the top. This is the meat of the thing!
return Tasks.find({}, { sort: { createdAt: -1 } });
},
incompleteCount() {
return Tasks.find({ checked: { $ne: true } }).count();
},
});
You only need to filter on ownerId which is used in this tutorial to associate a task with a user.
incompleteCount() {
return Tasks.find({ ownerId: Meteor.userId(), checked: { $ne: true } }).count();
},
Note that when you use multiple criteria like this they are implicitly ANDed.
I'm trying to display profile images in a list of users. The list populates all names correctly however I'm having trouble displaying the profile images. The profile images have a separate collection and they're being stored using slingshot S3. The collection is publishing correctly because I can see all the data using meteortoys:allthings. I assume it my js file or how I'm trying to access them in the template. Let me know if you need more info.
Path: userList.js
Template.userList.helpers({
userList: ()=> {
return Meteor.users.find({_id: { $ne: Meteor.userId() }});
},
profileImg: function(){
return Files.find({userId: this._id});
}
});
Path: userList.html
<template name="userList">
{{#each userList}}
{{#if profileImg url}}
<img src="{{url}}" alt="{{url}}" class="profileImg">
{{/if}}
{{profile.firstName}} {{profile.familyName}}
{{/each}}
</template>
userList.js
Template.userList.helpers({
userList() {
return Meteor.users.find({ _id: { $ne: Meteor.userId() } });
},
profileImg() {
return Files.findOne({ userId: this._id });
},
});
userList.html
<template name="userList">
{{#each userList}}
{{#with profileImg}}
<img src="{{url}}" alt="{{url}}" class="profileImg">
{{/with}}
{{profile.firstName}} {{profile.familyName}}
{{/each}}
</template>
The with will change the context for the img such that it actually has a url property. Returning the result of findOne in profileImg is also necessary here.
I have a template helper called notifications and I want to return 3 collection cursors to my template, so that I can view all
Template
<ul class="dropdown-menu notification">
{{#if notificationCount}}
{{#each notifications}}
{{> notification}}
{{/each}}
{{else}}
<li><span>No Notifications</span></li>
{{/if}}
</ul>
Helper
notifications: function() {
if (Meteor.user()) {
var accepted = Notifications.find({ origin: Meteor.user().username, status: 'ACCEPTED' });
var denied = Notifications.find({ rival: Meteor.user().username, status: 'DENIED' });
var confirmed = Notifications.find({ rival: Meteor.user().username, status: 'CONFIRMED' });
return accepted, denied, confirmed;
}
}
What is the best way to go about this? Thanks!
The literal answer to your question is to run fetch on all of the cursors and concatenate them into a single array.
return accepted.fetch().concat(denied.fetch(), confirmed.fetch());
Because all of your documents come from a single collection, you can alternatively use a more sophisticated query. Give this a try:
var username = Meteor.user().username;
return Notifications.find({
$or: [
{
origin: username,
status: 'ACCEPTED'
}, {
rival: username,
status: {$in: ['DENIED', 'CONFIRMED']}
}
]
});
I have a problem what looks like that this is not being set within my template. This didn't happen before, and I don't know what is changed.
My router.js
Router.map(function() {
this.route('gameRoom', {
path : '/game/:_id',
controller : GameRoomController
});
Controller
GameRoomController = RouteController.extend({
template : 'DetailsSubmit',
waitOn : function() {
return [
Meteor.subscribe('gameList', this.params._id),
Meteor.subscribe('gameInfo', this.params._id),
Meteor.subscribe('hintsList', this.params._id),
Meteor.subscribe('guessList', this.params._id),
Meteor.subscribe('imagesList', this.params._id),
Meteor.subscribe('allUsers')
// Meteor.subscribe('scoreList', this.params._id)
// stil in development will optimize this later
];
},
data : function() {
return Games.findOne(this.params._id);
}
});
So in my detailsubmit.html I have the following template (snippit)
<template name='DetailsSubmit'>
{{#if isWaitingOnAction}}
<div id="profileInfo">
<img src="http://placehold.it/90x90" alt=""/>
</div>
{{/if}}
</template>
If i type Games.find().fetch() it will output correctly:
_id: "5DDCNfWiBeHG4o7nQ"
active: true
finished: false
players: Array[2]
round: 0
theBoss: "JLApNut5rTpRxoL9S"
thePlayer: "o5aJETfWQTjEkZprf"
__proto__: Object
So I would expect my template would work correctly if I try one of the following commands:
And my helper:
Template.DetailsSubmit.helpers({
isWaitingOnAction: function() {
console.log(this) // return Object {}
console.log(Games.findOne(this._id)) // returns undefined in console
console.log(Meteor.userId()); // returns correct userId
}
})
What am I missing here?
Replace:
return Games.findOne(this.params._id);
with:
return Games.findOne({_id:this.params._id});
I'm having trouble getting Meteor.publish to update in response to a changing form field. The first call to publish seems to stick, so the query operates in that subset until the page is reloaded.
I followed the approach in this post, but am having no luck whatsoever.
Any help greatly appreciated.
In lib:
SearchResults = new Meteor.Collection("Animals");
function getSearchResults(query) {
re = new RegExp(query, "i");
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
}
In client:
Session.set('query', null);
Template.searchQuery.events({
'keyup .query' : function (event, template) {
query = template.find('.query').value
Session.set("query", query);
}
});
Meteor.autosubscribe(function() {
if (Session.get("query")) {
Meteor.subscribe("search_results", Session.get("query"));
}
});
Template.searchResults.results = function () {
return getSearchResults(Session.get("query"));
}
On server:
Meteor.publish("search_results", getSearchResults);
Template:
Search for Animals
<body>
{{> searchQuery}}
{{> searchResults}}
</body>
<template name="searchQuery">
<form>
<label>Search</label>
<input type="text" class="query" />
</form>
</template>
<template name="searchResults">
{{#each results}}
<div>
{{_id}}
</div>
{{/each}}
</template>
Update [WRONG]
Apparently, the issue is that the collection I was working with was (correctly) generated outside of Meteor, but Meteor doesn't properly support Mongo's ObjectIds. Context here and related Stackoverflow question.
Conversion code shown there, courtesy antoviaque:
db.nodes.find({}).forEach(function(el){
db.nodes.remove({_id:el._id});
el._id = el._id.toString();
db.nodes.insert(el);
});
Update [RIGHT]
So as it turns out, it was an issue with RegExp / $regex. This thread explains. Instead of:
function getSearchResults(query) {
re = new RegExp(query, "i");
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
}
At the moment, one needs to do this instead:
function getSearchResults(query) {
// Assumes query is regex without delimiters e.g., 'rot'
// will match 2nd & 4th rows in Tim's sample data below
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: query, $options: 'i'}} ] }, {limit: 10});
}
That was fun.
PS -- The ddp-pre1 branch has some ObjectId functionality (SearchResults = new Meteor.Collection("Animals", {idGeneration: "MONGO"});)
Here's my working example:
UPDATE the original javascript given was correct. The problem, as noted in the comments, turned out to be that meteor doesn't yet support ObjectIds.
HTML:
<body>
{{> searchQuery }}
{{> searchResults}}
</body>
<template name="searchQuery">
<form>
<label>Search</label>
<input type="text" class="query" />
</form>
</template>
<template name="searchResults">
{{#each results}}
<div>
{{id_species}} | {{name}} - {{_id}}
</div>
{{/each}}
</template>
Javascript:
Animals = new Meteor.Collection("Animals");
function _get(query) {
re = new RegExp(query, "i");
console.log("rerunning query: " + query);
return Animals.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
};
if (Meteor.isClient) {
Session.set("query", "");
Meteor.autosubscribe(function() {
Meteor.subscribe("animals", Session.get("query"));
});
Template.searchQuery.events({
'keyup .query' : function (event, template) {
query = template.find('.query').value
Session.set("query", query);
}
});
Template.searchResults.results = function () {
return _get(Session.get("query"));
}
}
if (Meteor.isServer) {
Meteor.startup(function() {
if (Animals.find().count() === 0) {
Animals.insert({name: "panda", is_active: true, id_species: 'bear'});
Animals.insert({name: "panda1", is_active: true, id_species: 'bearOther'});
Animals.insert({name: "panda2", is_active: true, id_species: 'bear'});
Animals.insert({name: "panda3", is_active: true, id_species: 'bearOther'});
}
});
Meteor.publish("animals", _get);
}