Meteor and filepicker-plus package - meteor

I am having a little bit of trouble outputting a image after a filepicker selection with the file picker plus package from meteor. How to I grab the uploaded image url or file path, so I can pass it into a form input and put it in a collection. Putting in into the collection isnt the part I am worried about its getting the path that I am having trouble with cheers.
All contained in postSubmit template.
I have a form with
<input type="filepicker" name="myName" />
and a img output in the same template
<img src="{{filepickerIdToUrl myName}}">
and a router file containg
Router.onBeforeAction(function(){
loadFilePicker('magickey');
//can leave out key if its in settings
this.next();
},{only:['postSubmit']});
Here is the full postSubmit template
<template name="postSubmit">
<form>
<label for="title">Title</label>
<input name="title" id="title" type="text" value="" placeholder="Name your post"/>
<button id="uploadImage" class="btn btn-info btn-sm"><i class="fa fa-upload"></i> Upload</button>
<input type="submit" value="Submit"/>
</form>
<img id="imagePreview" class="img-responsive" src="{{filepickerIdToImageUrl imageId placehold_it='500x350' h=200 w=300}}"/>
<button id="removeImage" class="btn btn-warning btn-sm"><i class="fa fa-trash-o"></i> Remove</button>
This is also my postSubmit events
Template.postSubmit.events({
'submit form': function(e) {
e.preventDefault();
var post = {
title: $(e.target).find('[name=title]').val(),
image: $(e.target).find('[name=image]').val()
};
Meteor.call('postInsert', post, function(error, result) {
// display the error to the user and abort
if (error)
return alert(error.reason);
Router.go('postPage', {_id: result._id});
});
}
});

Thanks to Nate and the google groups link above, I got it working.
Here is my solved code, Right now it only shows the preview on the form and you can remove it by clearing the session value, but it will be easy enough to grab that session value and put it into the form on submit.
Thanks again Nate.
Template.postSubmit.created = function(){
Session.setDefault("imageId", null);
Session.setDefault("imageKey", null);
};
Template.postSubmit.events({
'submit form': function(e) {
e.preventDefault();
var post = {
title: $(e.target).find('[name=title]').val(),
image: $(e.target).find('[name=image]').val()
};
Meteor.call('postInsert', post, function(error, result) {
// display the error to the user and abort
if (error)
return alert(error.reason);
Router.go('postPage', {_id: result._id});
});
},
'click #uploadImage':function(event, template){
event.preventDefault();
filepicker.pickAndStore(
{
mimetypes: ['image/gif','image/jpeg','image/png'],
multiple: false
},{
access:"public"
},
function(InkBlobs){
// the upload is now complete to filepicker - but the form hasnt persisted the values to our collection yet
Session.set("imageId", _.last(_.first(InkBlobs).url.split("/")));
Session.set("imageKey", _.first(InkBlobs).key);
// once the session changes are made, the form will now have the new values, including a preview of the image uploaded
},
function(FPError){
log.error(FPError.toString());
}
);
},
'click #removeImage':function(event, template){
event.preventDefault();
Session.set("imageId", "remove");
Session.set("imageKey", "remove");
}
});
Template.postSubmit.helpers({
'hideRemove':function(){
return Session.equals("imageId", null) || Session.equals("imageId", "remove");
},
'imageId':function(){
if(Session.equals("imageId", "remove"))
return "";
else
return Session.get("imageId") || "";
},
'imageKey':function(){
if(Session.equals("imageKey", "remove"))
return "";
else
return Session.get("imageKey") || "";
}
});

Related

Meteor not adding and showing tasks in web page, it just blinks and malfunctions (To create Todos list to add and delete tasks)

//Client side code in client\main.js
Tasks=new Mongo.Collection('tasks');
Template.tasks.helpers({
tasks:function () {
return Tasks.find({},{sort:{createdAt:-1}});
}
});
Template.tasks.events({
"submit .add-task":function (event) {
var name = event.target.name.value;
Meteor.call('addTask',name);
event.target.name.value='';
return false;
},
"click .delete-task":function (event) {
if(confirm('Delete Task?')){
Meteor.call('deleteTask',this._id);
}
return false;
}
});
Meteor.methods({
addTask: function (name) {
if (!Meteor.userId()) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function(taskId) {
Tasks.remove(taskId);
}
});
//Server side code in server\main.js
Tasks=new Mongo.Collection('tasks');
Meteor.methods({
addTask: function (name) {
if (!Meteor.userId()) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function taskId() {
Tasks.remove(taskId);
}
});
//Html page
<head>
<title>tasklist</title>
</head>
<body>
{{> tasks}}
</body>
<template name="tasks">
{{> loginButtons}}
<h1>Add Task</h1>
{{#if currentUser}}
<form class="add-task">
<label>Task Name</label>
<input type="text" name="name" placeholder="Add Task" />
<input type="submit" value="Submit" />
</form>
{{else}}
<p>Please log in to add tasks</p>
{{/if}}
<hr />
<h3>Tasks</h3>
<ul>
{{#each tasks}}
<li>{{name}}{{#if currentUser}} X{{/if}} </li>
{{/each}}
</ul>
</template>
Please help, in this when i reload page it first add and and shows in the web-page and if i delete the try todelete the added then screen doesnot show even added tasks which are in MongoDB.
And when i do console, there is an empty array of added tasks
If it "blinks" this often means that your Method worked client side but not server side. The insert worked on your Minimongo (client) but not on the real MongoDB (server). So Meteor decide to rollback your insert on Minimongo.
You must have a problem inside your Method server side:
You can't use Meteor.userId() server side in your Methods, you have to use this.userId.
To avoid mistakes, only use this.userId inside the Meteor Methods client or server side.
// Server side
Meteor.methods({
addTask: function (name) {
if (!this.userId) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: this.userId
});
},
deleteTask: function taskId() {
Tasks.remove(taskId);
}
});
In Meteor, you don't have to duplicate your Methods client AND server side.
Methods should always be defined in common code loaded on the client and the server to enable Optimistic UI.
You just have to define your Methods and your collection one time inside a folder loaded on client and server. For exemple you can put your code inside a folder named both/.

insert new doc via autoform hooks call meteor method

I want to insert a new document into db using autoform. Autoform hook calls a meteor method on server to insert the document.
I have this in template...
{{#autoForm collection="Reports" id="addReport" type="insert"}}
<div class="row">
<div class="col s6">
{{> afQuickField name='hours'}}
</div>
</div>
<button class="btn waves-effect waves-light modal-action modal-close"><i class="material-icons">save</i></button>
{{/autoForm}}
Then...
AutoForm.hooks({
addReport: {
onSubmit: function(insertDoc) {
Meteor.call('addReport', insertDoc, function(error, result) {
if (error) alert(error.reason);
});
return false;
}
}
});
then the method on server...
Meteor.methods({
addReport: function(insertDoc) {
var report = _.extend(insertDoc, {
userId: Meteor.userId(),
});
return Reports.insert(report);
}
});
I have a createdAt and updatedAt fields in collection, but they all have autoValue thus, I believe no need to do insertion from client or in the meteor method.
So collection with schema looks like this:
Reports = new Meteor.Collection('reports');
Reports.attachSchema(new SimpleSchema({
hours: {
type: Number,
label: "Number of hours",
decimal: true
},
createdAt: {
type: Date,
label: "Created Date",
autoValue: function() {
if (this.isInsert) {
return new Date;
} else {
this.unset();
}
},
denyUpdate: true
},
updatedAt: {
type: Date,
autoValue: function() {
if (this.isUpdate) {
return new Date()
}
},
denyInsert: true,
optional: true
},
"userId": {
type: String,
autoform: {
type: "hidden",
}
},
}));
When i run meteor, form displays, but submit does nothing. No visual cue as to if any error. No error message in both client and server console.
what am I doing wrong or missing?
Since #Cristo GQ got it right, I just want to make sure the answer is clear enough for future visitors of this thread
The onSubmit hook will be used only for autoForms with type='normal' or without any type= at all
On another note, the before.insert hook is just for type='insert' And there is no before.normal hook
This mean that when using the onSubmit hook, we have to do any "before work" (like adding currentUser to the doc) inside the onSubmit itself.
aldeed/meteor-autoform documentation:
// Called when form does not have a `type` attribute
onSubmit: function(insertDoc, updateDoc, currentDoc) {
Meteor.call()...
}
I'm following discovermeteor book, and I'm trying to use some methods of the book, but using the meteor-autoform package.
post_submit.html
<template name="postSubmit">
{{#autoForm collection="Posts" id="insertPost"}} <-- no type
<div class="form-group">
<div class="controls">
{{> afQuickField name='title' class='title form-control'}}
</div>
</div>
<div class="form-group">
<div class="controls">
{{> afQuickField name='description' class='description form-control'}}
</div>
</div>
<input id="send" type="submit" value="Send" class="btn btn-primary"/>
{{/autoForm}}
</template>
post_submit.js
var postSubmitHook = {
onSubmit: function(insertDoc){
Meteor.call('postInsert', insertDoc, function(error, result) {
if (error){
Bert.alert(error.reason, 'danger', 'growl-top-right');
$('#send').removeAttr('disabled');
return;
}
Router.go('postPage', {_id: result._id});
});
return false;
}
};
AutoForm.addHooks('insertPost', postSubmitHook);

Meteor quick form method not fired

I have a meteor form in which i don't want the user to be able to modify the id, so i omit the field. however i add it back to be able to proceed the update. when i submit the form, it gets stuck and the server is never called..
any help appreciated, thanks!
donators.html:
<template name="dInfo">
{{> dMove}}
{{#if getDoc}}
<label for="num">Numéro</label>
<input type="text" id="num" class="form-control" placeholder="ID" value="{{getDoc._id}}" readonly>
{{> quickForm schema=nwsc omitFields="_id" id="dUpt" doc=getDoc type="method" meteormethod="sayHi" buttonContent="Soumettre" buttonClasses="btn btn-lg btn-primary btn-block"}}
<button type="button" class="btn btn-lg btn-primary btn-warning btn-block btn-del">Supprimer</button>
{{/if}}
</template>
client side:
AutoForm.hooks({
dUpt: {
before: {
method: function(doc) {
doc._id = donators.find().fetch()[cursor.get()]._id;
}
},
onError: function(i, e) {
console.log(i);
console.log(e);
}
}
});
server side:
Meteor.methods({
sayHi: function(ins) {console.log(ins);},
updateDonator: function(ins) {
if(Meteor.userId() === null)
return;
if(ins._id === undefined)
return;
if(check(ins, dSchema) === false)
return;
dSchema.clean(ins);
ins.closed = false;
donators.update({_id: ins._id}, {$set: ins});
logs.insert({user: Meteor.userId(), email: Meteor.user().username, table: 'Donators', action:'Update', item: ins._id, date: new Date()});
}
});
Nothing is ever logged by sayHi, which is never called I suppose, and no error is ever fired.
Thanks!
According to the AutoForm documentation about callback hooks, in the before event you can modify the doc and return it by either:
// Then return it or pass it to this.result()
return doc; (synchronous)
return false; (synchronous, cancel)
this.result(doc); (asynchronous)
this.result(false); (asynchronous, cancel)
Your code does not return the modified doc. Add return doc; to the before -> method:
AutoForm.hooks({
dUpt: {
before: {
method: function(doc) {
doc._id = donators.find().fetch()[cursor.get()]._id;
return doc; // Add this line
}
},
onError: function(i, e) {
console.log(i);
console.log(e);
}
}
});
If AutoForm does not get a doc object back it will cancel the operation.

Image Upload not working in Meteor

In my meteor app I am uploading images and storing them in dropbox. It works fine when I am running the app in localhost. But as soon as I run the app after deploying it to meteor.com the upload fails to work.
This is my code in server.js
var createThumb = function(fileObj, readStream, writeStream) {
// Transform the image into a 10x10px thumbnail
gm(readStream, fileObj.name()).resize('10', '10').stream().pipe(writeStream);
};
var dropboxStore = new FS.Store.Dropbox("files", {
key: "",
secret: "",
token: "", // Don’t share your access token with anyone.
transformWrite: createThumb, //optional
})
Images = new FS.Collection("files", {
stores: [dropboxStore]
});
Images.allow({
'insert': function () {
// add custom authentication code here
return true;
}
});
Here is the link to meteor.com http://image_upload.meteor.com/.
I have tried changing dropbox to s3 but it still doesn't work. Could it be because it is hosted at meteor.com?
Looking forward for a solution.
Most likely it's because you're trying to use GraphicsMagick to resize the image in the transformWrite option, but meteor.com hosting servers do not have GraphicsMagick or ImageMagick installed.
https://github.com/CollectionFS/Meteor-CollectionFS/issues/299
You can use the meteor logs command to view the logs from your hosted meteor.com application to make sure that's the issue.
Edit
Here's some sample code for the jQuery cropper utility:
Template HTML:
<input type="file" style="visibility:hidden;width:1px" accept="image/gif, image/jpeg, image/png" class="profilePhotoFile">
<input type="button" id="btnEditPhoto" value="Edit Photo" class="btn btn-primary" style="width:160px"/>
<div class="modal fade" id="cropper-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div id="cropper">
<img src="" alt="Picture">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" id="btnSavePhoto">Save</button>
<button class="btn btn-default" id="btnCancel">Cancel</button>
</div>
</div>
</div>
</div>
Template JS:
Template.myTemplate.events({
'click #btnEditPhoto': function(event, template) {
$('.profilePhotoFile').click();
},
'change .profilePhotoFile': function(event, template) {
if (!event.target.files || event.target.files.length === 0) {
return;
} else {
var $inputImage = $(event.target);
var URL = window.URL || window.webkitURL;
var file = event.target.files[0];
var blobURL = URL.createObjectURL(file);
$image = $('#cropper > img');
$('#cropper-modal').modal();
$('#cropper-modal').on('shown.bs.modal', function() {
$image.cropper({
aspectRatio: 1.0,
autoCropArea: 1.0
}).cropper('replace', blobURL);
$inputImage.val('');
}).on('hidden.bs.modal', function() {
$image.cropper('destroy');
URL.revokeObjectURL(blobURL); // Revoke url
});
}
},
'click #btnSavePhoto': function(event, template) {
$image = $('#cropper > img');
//Change the width and height to your desired size
var base64EncodedImage = $image.cropper('getCroppedCanvas', {width: 10, height: 10}).toDataURL('image/jpeg');
$('#cropper-modal').modal('hide');
var newImage = new FS.File(base64EncodedImage);
Images.insert(newImage, function(err, fileObj) {
if (err) {
console.log(err);
} else {
//do something after insert
}
});
},
'click #btnCancel': function(event, template) {
$('#cropper-modal').modal('hide');
}
});

Meteor.js loginWithGoogle does nothing

I am working on my first Meteor app that uses OAuth for login. Prior to this, all of my projects have used only the accounts-password portions.
I have a simple login for with a button to login via Google:
<template name="login">
<form id="login" role="form">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" />
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" />
</div>
<button id="signin" class="btn btn-primary">Sign in</button>
<hr />
Or:<br />
<button id="loginWithFacebook">Login with Facebook</button>
<button id="loginWithGoogle">Login with Google</button>
<button id="loginWithTwitter">Login with Twitter</button>
</form>
</template>
I then have a event handler to capture the button click and call the loginWithGoogle:
...
"click #loginWithGoogle": function(e, t){
Meteor.loginWithGoogle({
requestPermissions: [],
loginStyle: "popup"
}, function(err) {
if (err) {
// TODO Need to do something here with the error...
console.log('Error: ', err);
} else {
Router.go('home');
}
});
}
...
On the server I setup OAuth for Google like thus:
ServiceConfiguration.configurations.remove({
service: "google"
});
ServiceConfiguration.configurations.insert({
service: "google",
clientId: "000000000000000",
loginStyle: "popup",
secret: "000000000"
});
Accounts.onCreateUser(function (options, user) {
console.log('Creating user: ' + user.username);
return user;
});
And in my route I have this:
if (Meteor.isClient) {
// Initialize the loading template before hand
Router.onBeforeAction('loading');
// Map the routes
Router.map(function() {
// Homepage
this.route('home', {
path: '/',
onBeforeAction: function() {
if (!Meteor.user()) {
console.log('User is not logged in. Displaying login form.');
Router.go('login');
} else {
console.log('User is already logged in:', Meteor.user());
}
}
});
// Login page
this.route('login', {
path: '/login'
});
});
}
So, I get the console log in the browser saying User is not logged in. Displaying login form., and when I click the Login with Google button I get the popup asking which Google account I want to use, then the confirmation page. But when I click the Accept button I get nothing. The Accounts.onCreateUser() doesn't seem to run, nor does the callback code on the loginWithGoogle(). How do I get this configured correctly so that the callback runs, and ultimately I am re-directed back to my homepage?
Your onCreateUser doesn't work because you don't have username specified.
Try using
if(user.services.google)
user.username = user.services.google.name
And by the way, why won't you use {{>loginButtons}}?

Resources