Im building and app using meteor and ionic and i want to display the name and the avatar of the user logged in.
I wrote this
<img src="{{Meteor.users().services.twitter.profile_image_url}}">
but it is not working. The same query in my console returns the right result. Is it becaus i removed autopublish ? Is there a way to overcome this?
Define a helper then use it for the URL
Template.templateName.helpers({
imageUrl: function(){
return Meteor.user().services.twitter.profile_image_url;
//you wrote Meteor.users() which should be user()
}
});
Then use it in your HTML
<img src="{{imageUrl}}">
EDIT:
Meteor.user() will return the current user object. If you want the user's profile picture to be visible somewhere to other users or even if that user is not logged in, you should store user's id and use that id to find & return user object or some specific data. For example, if you have a posts collection, you can do the following...
//inside your insert post method, save userId
owner: this.userId
//usage in template helper where you have the post data
userObj: function(){
return Meteor.users.findOne(this.owner) //returns user object.
}
//HTML
{{userObj.someData}}
To overcome removal of autopublish you can publish your collection data in a server javascript file and subscribe to same collection in a client javascript file.
Also you can do the following for your own image collections, better implementation in my point of view:
in a HTML file where you get your userId from router:
<img src="{{getUserProfileImage userId}}">
in a client javascript file like common.js
Template.registerHelper('getUserProfileImage', function(userId) {
return UserImages.findOne({userId: userId}).image;
}
});
You should better store each image in a collection like I did. Also using Meteor.user() directly may cause errors if user hasn't logged-in.
Please add javascript tag to your codes for formatting.
Related
May anyone help me? I have question about Meteor that how to keep data of the user logining can be published & subcribed in everywhere?
I created a collection like the Users collections of the Meteor and code a login function another, but after a user login, I can't keep their data subscribe in everywhere.
Sorry, I'm not good at English!
Thanks very much!
If a user is logged in, you can call Meteor.user() anywhere in your code to access the user object.
Try this:
import { Meteor } from 'meteor/meteor';
Meteor.publish(null, function userData() {
if (!this.userId) {
return this.ready();
}
return Meteor.users.find(this.userId);
});
Thanks all, I found the answer. It seems Meteor uses HTML5 localStorage
enter image description here
I have a Meteor app in which I insert a document (title, description, customer, ...) into a database. The app is using Autoform, Simple Schema and Collection2. I now want to add the possibility to upload a file to S3.
To keep things simple, I would present a filepicker as part of the 'Create Document' and once the file is uploaded, the URL field (from Autoform), should show the URL of the document on S3 (once uploaded) so that the URL is eventually stored in the document collection when the create button is clicked. I realise there might be better ways, but wanted to keep things simple for now.
I have tried to combine the tutorial here. The upload to S3 works, but I fail to get the URL for the uploaded file stored documents collection. The below screenshot shows the layout. Any idea's?
My current code can be found here.
There appear to be autoform add-on packages that specifically address S3 file upload (see the "Files" section here), but since you seem to be using this as learning opportunity, I'll try to explain how I'd do it using core meteor.
But first, before I forget, your uploader template is a child of #autoForm but has a form element of it's own. I think that will cause the generated HTML to have nested form elements (which is no-no). To fix that, I'd move the {{/autoForm}} before the {{> uploader}} and add an event handler for your submit button that submits the form using $('#documentForm').submit(). Note: I haven't tested that.
Now, on to your actual question. You are essentially asking how to modify something in a template (the value of the url field) from an event in a nested template (the uploader template). I'd do that as follows:
When an instance of the parent template is created, attach a ReactiveVar to it that will hold the URL of the uploaded file.
Template.adminDocumentNew.onCreated(function () {
this.url = new ReactiveVar();
});
Provide a helper to get the reactive var.
Template.adminDocumentNew.helpers({
url: function () {
return Template.instance().url;
}
});
Use the helper to set the value in the form.
{{> afQuickField name='url' value=url.get}}
Pass the reactive var to the uploader template as the data context:
{{> uploader urlVar=url}}
Use the reactive var to set the URL when the upload finishes (somewhere in upload-to-amazon-s3):
template.data.urlVar.set(url);
I've created a meteorpad that demonstrates the basic idea outside of the context of autoform and S3.
I am currently using EasySearch for my search solution for my app and I have a question on pub/sub of the search results.
Basically, the way the search works is that users will put into a search and a number of posts will be returned (I have a collections called Posts where I implemented the EasySearch).
I assumed EasySearch probably will automatically publish or subscribe depending on the results of the search queries, so I don't think I should worry about sending too many data to the client? (Correct if I am wrong).
However, the problem that I am having at the moment is that each posts is associated with a image from a collections called Images where my pub/sub is simply publish all and subscribe all from client and server and not related to the search at all.
I am just wondering does that mean I won't able to scale since I will be publishing every images to client regardless of the searches?
Post collection
Posts = new Mongo.Collection('posts');
Posts.initEasySearch(['firstName', 'lastName', 'degreeStudy', 'tags'], {
'limit' : 20,
'use' : 'mongo-db'
});
Posts.allow({
update: function(userId, post) { return ownsDocument(userId, post); },
remove: function(userId, post) { return ownsDocument(userId, post); },
});
Image collection
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("images")]
});
Template page for showing Search results
<template name="postPage">
<div class="container">
{{#ifEsHasNoResults index="posts"}}
<div class="jumbotron no-results"> <h1>No results found!</h1></div>
{{/ifEsHasNoResults}}
{{#ifEsIsSearching index="posts"}}
{{>loading}}
{{else}}
{{#esEach index="posts"}}
{{> postItem}}
{{/esEach}}
{{> esLoadMoreButton index="posts"}}
{{/ifEsIsSearching}}
</div>
</template>
In short, how can I make my pub and sub of the images collections related to the easySearch result?
I think you are confusing the cursor returned by your publication with the data itself. The cursor is like a way to make dynamic queries without having to load all your data (unless you do load all of them using for example an {{# each images}}). Read that for more info
This being said (no scaling issues ahead), I assume that inside your {{> postItem}} template, you have an image helper fetching the related image in your image collection.
This will work but keep this in mind: your user can open his console and get any image in your Images collection simply by doing an Images.find() related command. So it should be ok as long as you don't have private content. However if you do, you may want to use a method to fetch your image instead of publishing/exposing the whole collection.
I'm curious to know whether Meteor would be suitable for following, and how I would go about writing the code.
I'd like to create a webpage, where by the code in a specific "div" can be hotswapped on the fly to users currently looking at that page. (eg. the div contains some text, but then an image replaces it.) Ideally, the swap would be executed manually by the the webpage's admin through the click of a button, or some code fired off on the server or something. Regular viewers to the webpage would not be able to do this - they only see the live changes on the page.
real-life example:
live internet broadcast is off-air, therefore the "div" contains "off-air" text. live hotswap of code happens when broadcast goes on-air, and the viewers of the webpage now see the html5 broadcast player in the "div" instead. later it is swapped back once the broadcast goes off-air.
I'm completely new to the Meteor platform, so I consider myself a newbie :) Any help is appreciated.
You might better off by using a reactive div using data from a collection (I'm going to use an example with raw HTML but you might be better off implementing your own functionality with what content to display instead: i.e
Basically take advantage of reactivity over hot code swaps
Client side html code
<template name="home">
<div>
{{{content}}}
</div>
</template>
js code
if(Meteor.isClient) {
MyCollection = new Meteor.Collection("MyCollection")
Template.home.content = function() {
if(MyCollection.findOne()) {
return MyCollection.findOne().content
}
}
}
if(Meteor.isServer) {
MyCollection = new Meteor.Collection("MyCollection")
//Set an initial content if there is nothing in the database
Meteor.startup(function() {
if(!MyCollection.findOne()) {
MyCollection.insert({content:"<h1>Test content</h1><p>Test Data</p>"
}
}
//A method to update the content when you want to
Meteor.methods({
'updatecontent':function(newcontent) {
id = MyCollection.findOne()._id
MyCollection.update(id, {$set:{content:newcontent}});
return "Done"
}
}
You can update your content either in the mongo collection or with something like (in your web console, client side or server side javascript):
Meteor.call("updatecontent","New content",function(err,result) {
if(!err) {
console.log(result)
}
});
Which will update the code live when you use it.
I'm sorry it's quite long but the bulk of it is setting/updating the html. Its actually much nicer than a hot code swap which would refresh the user's page
I'm trying to display an alert to the user when data is added to the database. So I wrote (on the client side) :
Meteor.autosubscribe(function() {
ItemCollection.find().observe({
added: function(item) {
// Alert code
}
});
});
And I found that not only alerts are displayed when a new item is added to the database on the server side ( which I suppose is normal :) ) but alerts are also displayed for each previously added item when I refresh the page. I suppose Meteor fetch all the data from the Mongo database on startup (to populate the local Minimongo DB) and then fires 'added' event for each item added in the local database.
But is this the normal behavior ? How can I receive only items that are "truly" added in the database on the server ?
You are observing a cursor for the client side database and that database may not finish syncing until after the page is done loading, so the behavior makes sense. You may want to look into explicitly subscribing to a collection as discussed in the answer to this question.
If your data had a created_at field then you could observe items created after the page loads.
ItemCollection.find({created_at : {$gt: some_current_time}}).observe({
added: function(item) {
// Alert code
}
});