CollectionFS image url from cfsFileUrl handler not working - meteor

I have followed collectionFS guide and several other stackoverflow questions [here][1], but I still face an error in displaying the image. The broken image icon is shown and console prints "Resource interpreted as Image but transferred with MIME type text/html:". Any idea what i can do to solve this??
My code are as follows:
HTML
<template name="fileList">
{{#each images}}
{{name}}
<img src="{{cfsFileUrl 'default1'}}">
<br />
{{else}}
No Files uploaded
{{/each}}
</template>
Client JS
Template.fileList.helpers({
'images': function(){
return ImagesFS.find({}, {sort: {uploadDate:-1}});
}
});
Server JS
if(Meteor.isServer){
ImagesFS.fileHandlers({
default1: function(options) { // Options contains blob and fileRecord — same is expected in return if should be saved on filesytem, can be modified
console.log('I am handling default1: ' + options.fileRecord.filename);
console.log(options.destination());
return { blob: options.blob, fileRecord: options.fileRecord }; // if no blob then save result in fileHandle (added createdAt)
}
});
}

I got this working by manually adding the cfs-public-folder package via:
meteor add cfs-public-folder
Now files show in the browser, and the URL to
http://localhost:3000/cfs/<collectionFS name>/<imageId_fileHandler.ext>
works.

cfs-public-folder
is not working anymore on 0.9.x
please use:
.url()
like
MyColletionCFS.findOne().url()

Related

Meteor not displaying data from collection in html

I am trying to get data from a collection in meteor and using a helper passing it to a template.
Here is my code in collection:
Meteor.publish('displayCustomers', function tasksPublication() {
return Customers.find();
});
Below code in template JS file
Template.customerlist.onCreated(function() {
Meteor.subscribe('displayCustomers');
});
Template.customerlist.helpers({
displayCustomers :function(){
console.log(Customers.find({}));
return Customers.find({});
},
});
Template:
<template name="customerlist">
<h1>All registered users</h1>
{{#each displayCustomers}}
{{fname}}
{{/each}}
</template>
It is only displaying HTML content i.e. <h1>All registered users</h1>
Check that your publication is returning values to the client with this MiniMongo chrome extension
Check to make sure Customers is defined on the server and that your publish block is running only on the server.
Also I would toss a debugger into your onCreated block to make sure that your subscribe is being initialized.
Other than that, your code looks fine. I would try installing MeteorToys Mongol for client pub/sub debugging. https://atmospherejs.com/msavin/mongol
You need to actually fetch documents in your template :
Template.customerlist.helpers({
displayCustomers :function(){
return Customers.find().fetch(); //will return an array with all published documents
},
});

Meteor Iron:Router Template not Rendering

I have a main page which lists a few text items ("Ideas"), which are clickable links. Clicking on them should take you to a page where you can edit them. Here's my html:
<head>
<title>Ideas</title>
</head>
<body>
</body>
<template name="Ideas">
<ul>
{{#each ideas}}
{{> idea}}
{{/each}}
</ul>
</template>
<template name="idea">
<li>{{text}}</li>
</template>
<template name="ShowIdea">'
<div class="editable" contentEditable="true">{{text}}</div>
</template>
I've added Iron:Router to my project to allow for moving between the pages. Here's the javascript:
Ideas = new Mongo.Collection("ideas");
if (Meteor.isClient) {
Router.route('/', function() {
this.render('Ideas');
});
Router.route('/idea/:_id', function() {
var idea = Ideas.findOne({_id: this.params._id});
this.render('ShowIdea', {text: idea.text});
});
Template.Ideas.helpers({
ideas: function () {
return Ideas.find({});
}
});
}
I inserted a single idea to my Mongo DB using the Meteor Mongo command line tool. That single item shows up properly on my main page. Here's what the HTML looks like in my debugger for the main page:
<html>
<head>...</head>
<body>
<ul>
<li>
The first idea ever
</li>
</ul>
</body>
</html>
Clicking on that link takes me to a new page with an address of:
http://localhost:3000/idea/ObjectID(%22550b7da0a68cb03381840feb%22)
But nothing shows up on the page. In the debugger console I see this error message + stack trace, but it means nothing to me since it all seems to be pertaining to iron-router and meteor, not code which I actually wrote:
Exception in callback of async function: http://localhost:3000/Idea.js?2fd83048a1b04d74305beae2ff40f2ea7741d40d:10:44
boundNext#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:35
http://localhost:3000/packages/meteor.js?e53378596562e8922a6369c955bab1e047fa866b:978:27
onRerun#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:520:13
boundNext#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:35
http://localhost:3000/packages/meteor.js?e53378596562e8922a6369c955bab1e047fa866b:978:27
onRun#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:505:15
boundNext#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:35
http://localhost:3000/packages/meteor.js?e53378596562e8922a6369c955bab1e047fa866b:978:27
dispatch#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:448:7
_runRoute#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:543:17
dispatch#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:844:27
route#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:710:19
boundNext#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:35
http://localhost:3000/packages/meteor.js?e53378596562e8922a6369c955bab1e047fa866b:978:27
boundNext#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:371:18
http://localhost:3000/packages/meteor.js?e53378596562e8922a6369c955bab1e047fa866b:978:27
dispatch#http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:448:7
http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:390:21
_compute#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:308:36
Computation#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:224:18
autorun#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:499:34
http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:388:17
nonreactive#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:525:13
dispatch#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:387:19
dispatch#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1688:22
onLocationChange#http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1772:33
_compute#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:308:36
_recompute#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:322:22
flush#http://localhost:3000/packages/tracker.js?21f0f4306879f57e10ad3a97efe9ea521c5b5775:452:24
And then it ends with this warning message:
Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?
I don't have an onBeforeAction (I'm not even sure what that is)... so I don't think that message pertains to me?
I just started using Meteor the other day and just added iron-router not 24 hours ago, so I'm a bit lost here. Any pointers on how I can debug and fix this would be great.
Two things need fixing:
When you insert documents from the shell they are assigned _id values which are mongo ObjectIDs, whereas meteor defaults to using strings. This explains the weird URL. To avoid this problem, it's generally best to initialize your data from the server. Here's an example:
if (Meteor.isServer) {
Meteor.startup(function() {
if (Ideas.find().count() === 0) {
Ideas.insert({text: 'feed the cat'});
}
});
}
Now after a $ meteor reset you will always start with one cat-related idea.
If you wish to pass a context to your template, you'll need to use the data attribute like so:
Router.route('/idea/:_id', function() {
this.render('ShowIdea', {
data: function () {return Ideas.findOne({_id: this.params._id})}
});
});
See this example from the docs. After making those changes, the code worked correctly for me.

Using dropzone.js with meteor.js

I am confused about something.
I am trying to use the dropzone.js meteor package (http://atmospherejs.com/dbarrett/dropzonejs) with my meteor application but I could not find any example about it. In the documentation it says:
Use the template like this
{{> dropzone url='http://somewebsite.com/upload' id='dropzoneDiv'}}
and
it will post any uploaded files to the url of your choice.
So if I write,
{{> dropzone url='http://localhost:3000/home' id='dropzoneDiv'}}
as soon as I drop the image, is it going to upload it to /public/home folder? I mean is the package handling server-side saving image too?
If not, can you please give me some tips about how I can handle the server side saving?
Thank you
Dropzone can be a bit confusing:
First you should get a file management system for Meteor. The standard right now is CollectionFS:
https://github.com/CollectionFS/Meteor-CollectionFS
Then you need to add a file system. I use GridFS, which breaks up large files into chunks and stores them for you into Mongo:
https://github.com/CollectionFS/Meteor-cfs-gridfs/
Follow the instructions for creating, publishing, and subscribing to your new, special, FS Collection:
example for creating the collection:
MyImages = new FS.Collection('myImages', {
stores: [new FS.Store.GridFS("myImages")]
});
After those two are installed, create your dropzone:
<template name="imageUpload">
<form action="/file-upload" class="dropzone" id="dropzone"></form>
</template>
Then in your javascript:
Template.imageUpload.rendered = function(){
if (Meteor.isClient){
var arrayOfImageIds = [];
Dropzone.autoDiscover = false;
// Adds file uploading and adds the imageID of the file uploaded
// to the arrayOfImageIds object.
var dropzone = new Dropzone("form#dropzone", {
accept: function(file, done){
MyImages.insert(file, function(err, fileObj){
if(err){
alert("Error");
} else {
// gets the ID of the image that was uploaded
var imageId = fileObj._id;
// do something with this image ID, like save it somewhere
arrayOfImageIds.push(imageId);
};
});
}
});
};
};
I'm assuming, it doesn't show upload progress, because its instant with meteor.
You are updating mini-mongo location in-browser, so the changes are immediate.
Meteor DDP then handles the glue to get it to the server, and then pushing those changes to the other clients that might be subscribed. That "instant" update is the meteor magic. Alert yourself, or log to console on success. You can also check the db via MyImages.find().fetch().
If they are there, all done.
Please find below link(example of dropzonejs):
https://github.com/devonbarrett/meteor-dropzone/tree/master/example-app
Put {{>dropzone url="/upload" id="template-helper"}} In your template
<template name="test">
{{>dropzone url="/upload" id="template-helper"}}
</template>
Then at server side:
if (Meteor.isServer) {
Meteor.startup(function () {
UploadServer.init({
tmpDir: process.env.PWD + '/public/uploads',
uploadDir: process.env.PWD + '/public/uploads',
checkCreateDirectories: true,
uploadUrl: '/upload'
});
});
}

Pass data to a dynamic template

With meteor updates up to 0.8 my old code stopped working.
Handlebars.registerHelper('getTemplate', function(id, context) {
return Template[id](context);
});
<template name="main">
....
{{{getTemplate templateName context}}}
....
</template>
//somewhere in other template
Template.main.context = {name:value};
This way I was able to render a custom template with custom data. Now I can't find the way to pass context to the dynamic template. With blaze both templateName and context is undefined. Any advice?
Meteor >= 0.8.2
You can use the UI.dynamic helper render a template with a context which are both specified dynamically. For more details, check out this issue.
Meteor < 0.8.2
Both of these issues are addressed on this page in the meteor wiki.
Handlebars.registerHelper is now UI.registerHelper as seen here.
Examples of how to dynamically render templates are shown here.
update
Actually, given the requirements, a solution doesn't seem very obvious to me. If you are willing to use session variables to set the template name and context, AND only have one dynamic template in your main template. You could do something like this:
<body>
{{> main}}
</body>
<template name="main">
{{> getTemplate context}}
</template>
<template name="dogs">
<p>There are {{animals}} dogs!</p>
</template>
<template name="cats">
<p>There are {{animals}} cats!</p>
</template>
Session.setDefault('templateName', 'dogs');
Session.setDefault('templateContext', {animals: 10});
Template.main.getTemplate = function() {
return Template[Session.get('templateName')];
};
Template.main.context = function() {
return Session.get('templateContext');
};
This was brought up on the meteor-core list and #dgreensp, MDG core dev working on Blaze, opened Ticket #2007 - How to render a template to HTML with data so they definitely know about this and I'd expect a fix to land soon after 0.8.0.
He also included the following workaround:
var toHTMLWithData = function (kind, data) {
return UI.toHTML(kind.extend({data: function () { return data; }}));
};
The github ticket has further discussion and alternate code snippets that you may find useful.

Meteor using a local connection results in error: insert failed: 404 -- Method not found

I've got a meteor collection on the client side
Friends = new Meteor.Collection("Friends");
Meteor.subscribe("Friends");
I have a user authenticate with facebook and I want to grab a list of their friends:
FB.api("/me/friends? auth_token="+response.authResponse.accessToken,
function(response){
for (i = 0; i<response.data.length;i++){
Friends.insert(response.data[i]);
}
);
I have a function to get that list:
Template.Friends.all_friends = function(){
return Friends.find();
}
I have a template that would like to display all the friends on the screen:
<template name="Friends">
{{#each all_friends}}
<div id="{{id}}" class="friend">
<img src="http://graph.facebook.com/{{id}}/picture" />
{{name}}
</div>
{{/each}}
</template>
What appears to be happening on the page is that all the friends DO flash up on the screen for a split second then immediately the screen flashes back to blank.
In the javascript console the message appears once per friend I have (yes, it is more than zero, thanks for asking)
insert failed: 404 -- Method not found
So! What have I missed? Anyone?
You need that Collection declaration on both the client and the server.
// common code, do not put under /client or inside Meteor.is_client test
Friends = new Meteor.Collection("Friends");
If you want to use Collection only on Client side and you don't need to save that data to server you can declare your collection in "client" folder or in .isClient() function by passing null to the constructor like this:
if(Meteor.isClient()){
// Some other code
...
onlyClientCollection = new Meteor.Collection(null);
// Some other code
...
}

Resources