I am using CollectionFs to Upload profile pictures. Uploading and storing the image is successful. I can insert and show the image alright for one user but the
problem is:
For multiple users, when a user visit other users profiles, He sees his own picture rather than seeing the profile owner's picture!
I understand its the mongo query I have in my helper function thats causing the issue but can't just get it to work no matter how many "This._id" I Try.
Here is the javaScript
Router.route('show',{
path:'/list/:_id',
data: function(){
return Main_database.findOne({_id: this.params._id});
}
});
Template.upload.events({
'change #exampleInput':function(event, template){
var file = $('#exampleInput').get(0).files[0];
fsFile = new FS.File(file);
fsFile.metadata = {ownerId:Meteor.userId()}
Images.insert(fsFile,function(err,result){
if(!err){
console.log("New images inserted")
}
})
}
});
Template.profile.helpers({
profilePic: function () {
return Images.find({'metadata.ownerId':Meteor.userId()});
}
});
And here is the html:
<template name="upload">
<div class="container">
<div class="row">
<input type="file"
id="exampleInput">
</div>
</div>
</template>
<template name="profile">
{{#each profilePic}}
<img src="{{this.url}}"
height="400" width="400"
class="img-circle">
{{/each}}
</template>
Thanks
B.s : after following the answer given, I attached the photo in the profile.xxx field. But its still showing the wrong picture. The mongo query is still showing the wrong picture.
here is the code,
Router.route('show',{
path:'/list/:_id',
data: function(){
return Main_database.findOne({_id: this.params._id});
}
});
Template.upload.events({
'change #exampleInput':function(event, template){
var file = $('#exampleInput').get(0).files[0];
newFile = new FS.File(file);
newFile.metadata = {'ownerId':Meteor.userId()};
Images.insert(newFile,function(err,result){
if(!err){
console.log(result._id);
Meteor.users.update(Meteor.userId(),{
$set: {
'profile.profilePic': result._id
}
});
}
});
}
})
// .....................profile pic.............
Template.profile.helpers({
profilePicture: function () {
return Images.find({'_id':Meteor.user().profile.profilePic});
}
});
Finally was able to do it. Being a beginner, I was stuck at uploading images and then showing them for my users for days. Tried almost each method out there, none worked. asked everywhere, none of the answer worked. Finally , a dead simple package from cosio55:autoform-cloudinary worked like magic!!! Just take a look at the problems I faced while using these packages:
1. cfs:ui
{{#with FS.GetFile "images" selectedImageId}}
// image url
{{/with}}
problem:
with this was I couldn't get the selectedImageId .
2. cfs:gridfs
problem :
grid fs stores image in a separate collection. My user list uses iron router to show the user list form another collection. Image was getting uploaded into the images collection. But For the love of my life, I couldn't show them correctly. Each user was seeing his own picture rather than the profile owner's picture. happened because of a wrong mongo query but I couldn't get the right query. Tried attaching the photo in the profile.profilePicture, but same problem of wrong image stayed.
And I had to put the upload photo in a separate page and NOT in the autoform.
3. lepozepo:cloudinary
Problem:
Image uploaded fine. But had problem getting /storing the image url. Couldn't get
And I had to put the upload photo in a separate page and NOT in the autoform.
public_id ????? Got lost there.
4. autoform-file by yogiben
same problem as GridFs.
Finally with this cosio55:autoform-cloudinarypackage took me just a minute to figure things out. A minute vs days of other big name packages!!!!
:smiley:
<div> <img src=" {{image}}" alt=""> Image </div>
just add {{image} in the img source and thats it. The image url is stored in the same collection autoform stores everything.
Cheers Mates.
For the profilePic it will return the same user profile image, instead you should do a query by _id and not metadata.ownerId
To do that you should have a reference for the image in users collection when you insert the image something like:
Images.insert(file, function (err, res) {
if (!err) {
Meteor.users.update(Meteor.userId(),{
$set: {
'profile.profilePic': res._id,
}
});
});
And when you need to display the image you can do something like:
Template.profile.helpers({
profilePic: function () {
return Images.find({'_id':Meteor.user().profile.profilePic});
}
});
First things first: Meteor.user() and Meteor.userId() always shows data for CURRENTLY logged-in user.
So when user wants to see his own profile, it is right to use your current Template helper like this:
Template.profile.helpers({
profilePic: function () {
return Images.find({'metadata.ownerId':Meteor.userId()});
}
});
But when user goes to another user's profile, you should fetch that user's info like this: Meteor.user("another-user-id");
So how to do this? Let's suppose that you have set routing in you Meteor app with Iron Router or Flow Router and for user profile page you have set-up route path something like this: /user/:_id.
Now, you want to publish only this user's data like this in your publications on the server:
Meteor.publish("userData", function(userId){
return = Meteor.users.find({"_id": userId});
});
...and subscribe to this publication on client (we'll use Template-level subscriptions!)
With Iron Router:
var userId;
Template.profile.onCreated(function() {
var self = this;
self.autorun(function() {
userId = Router.current().params._id;
self.subscribe("userData", userId);
}
});
Template.profile.helpers({
profilePic: function () {
return Images.find({'metadata.ownerId': userId});
}
});
With FlowRouter:
var userId;
Template.profile.onCreated(function() {
var self = this;
self.autorun(function() {
userId = FlowRouter.getParam("_id");
self.subscribe("userData", userId);
}
});
Template.profile.helpers({
profilePic: function () {
return Images.find({'metadata.ownerId': userId});
}
});
Related
I loaded Iron:Router with my Meteor, and now I'm having difficulties loading both all of a collection, and one specific entry.
What I'm trying to do: In the Nav Bar, I want to list all of a user's previous entries. I got that working great. It lists each into a drop down, provides a proper link, and loads up only what the user has previous input. In the body it's suppose to load up specific information for each entry.
Whats not working: It's either not giving me a findOne() where the params._id equal the id in the route, or it's not loading anything. The location is correct. It's just not loading the info like it should.
UPDATE: I moved some things around and got the 'name' field to print out, still not able to get it to verify owner just yet. Console prints out: "Exception in template helper: ReferenceError: currentCharacter is not defined" Replacing with current code.
What am I doing wrong? Below is the code:
Route:
this.route('character/:_id', {
template: 'character',
subscriptions: function() {
return Meteor.subscribe("characterlist");
return Meteor.subscribe("characterlist", this.params._id);
},
data: function () {
var routeid = this.params._id;
return {
currentCharacter: CharList.findOne({_id: routeid}),
characterlist: CharList.find({'owner':Meteor.userId()})
};
}
});
Template Helper Class:
Template.character.helpers({
characterlist: function () {
return CharList.find({}, {sort: {createdAt: -1}});
},
currentCharacter: function () {
return CharList.findOne({'_id':Router.current().params._id});
},
isOwner: function () {
return currentCharacter.owner === Meteor.userId();
}
});
HTML:
<template name='character'>
<div class="container-body">
{{#if currentUser}}
<div class="well">
{{currentCharacter.name}}
{{#with currentCharacter}}
{{#if isOwner}}
<p>Character: {{name}}</p>
{{else}}
<p>You are not approved to make spends for this character.</p>
{{/if}}
{{/with}}
</div>
{{else}}
<h4>Please log in.</h4>
{{/if}}
</div>
</template>
Let me sigh metaphorically out loud online. Like usual when I ask for help I find what i did wrong.
It needs to get "this" object and pull the "owner" type out. Once it has "this.owner" it can verify the user is of course the correct owner. I was trying to be smart and didn't realize it was asking for the wrong information for four hours! Code below:
isOwner: function () {
return this.owner === Meteor.userId();
}
I am trying to create a route for a user profile page, but when I visit the route it shows up as a completely blank page and with no errors in the terminal. Nothing whatsoever is shown, including static HTML. Here's the code:
routes.js
Router.route('/user/:_id', function () {
this.render('user');
}, {
name: 'user',
data: function(){
return Users.findOne({_id: this.params._id})
}
});
user.html
<template name="user">
<p>hello</p>
</template>
At the moment, I am using the default user accounts package and have not added any publication or subscription code.
Are you sure Users is an existing collection?
At the moment, I am using the default user accounts package and have
not added any publication or subscription code.
In that case, with autopublish enabled, your problem is probably solved by changing
data: function(){
return Users.findOne({_id: this.params._id})
}
into:
data: function(){
return Meteor.users.findOne({_id: this.params._id})
}
although it's strange this doesn't throw an error in your console...
Not sure if this is the reason, but I think that with multiple options for the route, you should incapsulate this.render in an action parameter. Something like this:
Router.route('/user/:_id', {
name: 'user',
data: function() {
return Users.findOne({_id: this.params._id})
},
action: function () {
this.render('user');
}
});
Source
I get an error in the terminal: "Users is not defined":
http://meteorpad.com/pad/eciFidhwHmLhjWmF3/Leaderboard
In your data function, try substituting Meteor.users.findOne({_id: this.params._id})
If you fix the HackPad I listed, Meteor.users won't work since the current version of HackPad doesn't support a late enough version of Meteor with Meteor.users. However, if you comment out your data function, you should at least see the page.
I'm trying to publish all the usernames to the clients, even if not signed in. For that, on the server I have:
Meteor.publish("users", function() {
return Meteor.users.find({}, {fields : { username : 1 } });
});
And on the client:
Meteor.subscribe("users");
However, when I try to access the Meteor.users collection, I find nothing there.
(This is essentially the same as the question here: Listing of all users in the users collection not working first time with meteor js, only without checking the roles for admin first. Still doesn't seem to work..)
I'm probably missing something silly..
I find the same issue, and after doing a research i find this package, i think it may should help you.
Take a look and hope it help you
Update
First move the subscription to the /lib folder, just to make sure its the first thing meteor do when start, also change a little bit the subscription like this on the /lib, folder.
Tracker.autorun(function() {
if(Meteor.isClient) {
if (!Meteor.user()) {
console.log("sorry you need to be logged in to subscribe this collection")
}else{
Meteor.subscribe('users');
}
}
});
For better security we just subscribe to the users collection when the client its logged in
This code outputs all the usernames to the clients, even if not signed in (in this case on /users page):
server/publications.js:
Meteor.publish("userlist", function () {
return Meteor.users.find({},{fields:{username:1}});
});
client/users_list.js:
Template.usersList.helpers({
users: function () {
return Meteor.users.find();
}
});
client/users_list.html:
<template name="usersList">
{{#each users}}
{{username}}
{{/each}}
</template>
lib/router.js (using iron:router package):
Router.route('/users', {
name: 'usersList',
waitOn: function(){
return Meteor.subscribe("userlist");
}
});
Hope it helps.
Ok so I'm not sure why I can't render the code. First if I console.log users.content I get the content I want but I'm some how not able to pass it to a textarea so that it show's it...
Users = new Meteor.Collection("users");
if(Meteor.is_client){
Template.inputUser.code = function(){
var el = Users.find({name:"oscar"});
el.forEach(function(users){
console.log(users.content);
})
}
}
And then on my html template I have
<body>{{> inputUser}}</body>
<template name="inputUser">
<textarea>{{content}}</textarea>
</template>
And I would have a record on the db suck as so
if(Meteor.is_server)
Users.insert({name:"oscar",content:"hello world"})
Thanks for your help guys.
Firstly your method Template.inputUser.code should return something, you should also note that it wouldn't be called with that template either as it needs a {{code}} call in it rather than {{content}}
The second point is database contents are not always available if you have disabled the autopublish package, if so check out using publish(in the server code) and subscribe(in the client code): http://docs.meteor.com/#meteor_subscribe you can use this to check when the client has all the data to display. Something like:
Meteor.subscribe('allusers', function() {
Template.inputUser.code = function(){
var user = Users.findOne({name:"oscar"});
return user.content;
}
});
...
Meteor.publish('allusers', function() {
return Users.find();
});
I am encountering a problem with subscribing/publishing in Meteor. I've written an example Meteor app to help narrow the scope of the problem.
I am publishing a collection on the server that is filtered by a parameter passed in through a subscription on the client. This subscription is within an autosubscribe, which leverages a session variable to reactively update the subscriptions.
When changing the state of this particular session variable, the collection on the client isn't getting updated properly, or at least that's what I gather. I've spent the whole day on this and have not found an issue in code I control. I suspect I'm either not understanding how to setup proper pub-sub in Meteor, or there's a problem within Meteor.
To reproduce the problem, start a new Meteor project and use the following (Make sure to remove the autopublish package when trying it out):
HTML (test.html for example):
<head>
<title>pubsubbug</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example showing possible bug in Meteor wrt pub-sub</h1>
<p><button name="showall">show all ({{showall}})</button></p>
<div style="float:left;width:400px;">
<h2>Notes:</h2>
<ul>
{{#each notes}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
<div style="float:left;">
<h2>Notes (copied):</h2>
<ul>
{{#each notes_copied}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</template>
JS (test.js for example)
if (Meteor.is_client) {
Notes = new Meteor.Collection("notes_collection");
NotesCopied = new Meteor.Collection("notes_collection_copied");
Session.set("showall", false);
Meteor.autosubscribe(function () {
Meteor.subscribe("notes_subscription", Session.get("showall"), function () {
console.log("Notes count:", Notes.find().count());
});
Meteor.subscribe("notes_subscription_copied", Session.get("showall"), function () {
console.log("Bug? This isn't getting called.");
console.log("NotesCopied count:", NotesCopied.find().count());
});
});
Template.main.notes = function () {
return Notes.find();
};
Template.main.notes_copied = function () {
return NotesCopied.find();
};
Template.main.showall = function () {
return Session.get("showall");
};
Template.main.events = {
"click button[name='showall']": function (evt) {
Session.set("showall", !Session.get("showall"));
}
};
}
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
var getNotes = function (showall) {
if (showall) {
return Notes.find({}, {sort: {title: 1}});
} else {
return Notes.find({visible: true}, {sort: {title: 1}});
}
};
Meteor.publish("notes_subscription", function (showall) {
// By sending the Notes back with the same uuid as before, the
// client end seems to get confused:
return getNotes(showall);
});
Meteor.publish("notes_subscription_copied", function (showall) {
var notes = getNotes(showall);
var self = this;
// Copy notes into a new notes collection (see NotesCopied on client).
// By generating a new uuid, we don't get an issue with the notes
// on the client getting screwed up:
notes.forEach(function (note) {
var uuid = Meteor.uuid(); // note._id will cause same problem
self.set("notes_collection_copied", uuid, {title: note.title});
});
self.flush();
self.complete();
});
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1 (always visible)", visible: true});
Notes.insert({title: "Note #2 (always visible)", visible: true});
Notes.insert({title: "Note #3 (always visible)", visible: true});
Notes.insert({title: "Note #4 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #5 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #6 (only visible when showall true)", visible: false});
}
});
}
An explanation of what you will be seeing:
There will be a button that, when clicked, simply toggles a session variable (showall) between true and false.
Two subscriptions exist (within an autosubscribe), one that exemplifies the bug, and another that is suffixed with _copied, which is a test to demonstrate that when the collection in question is "copied" and new uuid's are assigned, the results are displayed properly. I couldn't figure out what to do with this particular bit of info... I don't want new uuid's.
So basically, when the show all button is clicked repeatedly, the first column Notes: will display incorrect results, and after a few clicks won't show anything.
On the other hand, the second column Notes (copied):, whose uuid's are re-generated each time, shows up correctly.
Is this a bug? Or is there a proper way to do this?
EDIT: Example above live over at http://pubsubbug.meteor.com/
Not experiencing your bug on the developer branch on Windows. Since this is the case, it is a good sign that there is nothing wrong with your code. It appears that you see something buggy regarding the subscriptions and/or how Mongo queries.
Meteor itself is most likely running the stable (= master) release on their hosting, so you will have to try a different approach or wait for a new release. Unless you can support running on devel...