Meteor.publish is not a function - meteor

I have a publications.js file that ONLY includes
Meteor.publish('org', function(_id){
return Organizations.findOne(_id);
});
When things render I get this in the console:
Uncaught TypeError: Meteor.publish is not a function
What am I missing here... I'm sure it's painfully obvious.

You are probably accidentally running the code on the client. You have two choices:
Place the publish code in a file under the /server directory in your app.
Wrap the above inside of an if (Meteor.isServer) {} block.
(1) Has the advantage of not transmitting the publish code to the client.
Suggested reading: Structuring your application.

If the file is at the root, you need to wrap it with:
if ( Meteor.isServer ) {
/* ... */
}
The Meteor.publish method only exists on the server.

Related

Can someone explain how Meteor.defer() works?

So... Meteor.defer(function(){ // stuff }) isn't in the docs:
https://github.com/meteor/meteor/issues/2176
But this links seems to say that it's simply equivalent to
Meteor.setTimeout(function(){ // stuff }, 0);
If that's the case, how does this do, um, anything? It's basically saying "wait for 0 ms and then run the function".
So... it runs the function instantly.
What am I missing here? Is this kind of like Tracker.afterFlush or something? Does it somehow wait for "things" (what kind of things?) to finish before running?
I see Meteor.defer() a lot on SO being used as a bit of a hack on added helper methods to run after the dom is (somewhat) loaded - basically to get the same effect as running code inside of a Template.foo.rendered method.
However, the main (and best) use of Meteor.defer is to run a task asynchronously.
Let's say we have an app where we are sending an email. On the server, it may take several seconds for that to process inside of a meteor method, slowing down your application drastically. However, if you wrap that process in a Meteor.defer the email processing won't block execution, the email still sends (when it gets a chance, not instantly), but everything runs much faster, since the code that follows isn't waiting. There is a great example lesson about deferring execution at Bulletproof Meteor.
You can actually get the same effect with a setTimeout(f,0) - if you have a slow function, you could wrap it in the setTimeout and the rest of the code will complete, and 'defer' the slow process in the timeout, so although it doesn't seem like it, setTimeout(f,0) does actually have a pretty useful purpose!
To see an example of this in action, here's a fiddle, open the console and watch where 'foo' logs.
I faced some issue in my project because of asynchronous callback. Inside onCreated i was making a server Meteor.call and set the response inside reactiveVar. And i was doing something inside onRendered with that reactiveVar. Every time reactiveVar was showing undefined.
So i used Meteor.defer(function(){...}) inside onRendered and it sloved my issue.
Here is some demo with and without using Meteor.defer()
Template.myTemplate.onCreated(function () {
var instance = this;
instance.myTemplateModel = new ReactiveDict();
Meteor.call('all-user', function(err, res){
if(res){
console.log('inside callback');
instance.myTemplateModel.set('users', res);
}
});
});
Template.myTemplate.onRendered(function () {
var instance = this
console.log('rendered start');
Meteor.defer(function(){
console.log(instance.myTemplateModel.get('users'));
});
console.log('render end');
});
Console:
/*Without Meteor.defer()*/ | /*With Meteor.defer()*/
render start | inside callback
undefined | render start
render end | render end
inside callback | [Object, Object, Object]

MeteorJs "loginWIthPassword" seems not to work in method

It seems that the "Meteor.loginWithPassword" function does not work when called in a method.
I want to create my login form with autoforms and so I created a callback method which get called after a user submitted the login form. The form gets called the right way but the loginWithPassword function does not seems to work.
This is my method (on Client & Server side)
Meteor.methods({
autoform_test_login : function (doc) {
console.log('Called login method');
if (Meteor.isClient) {
Meteor.loginWithPassword('test', 'test', function(e) {
if (e) {
console.log(e);
}
});
}
}
});
My autoforms calls this method when submitting with:
{{#autoForm schema="Schema_Login" id="form_login" type="method" meteormethod="autoform_test_login"}}
....
When submitting this form I get this error:
Error: No result from call to login {stack: (...), message: "No result from call to login"}
When I now open my Browser console and type in:
Meteor.call('autoform_test_login');
I will get the same error.
But: When I type the following in my console it works (The error now is: Username not found):
Meteor.loginWithPassword('test', 'test', function(e) {
if (e) {
console.log(e);
}
});
My method do absolutely nothing else then this snipped so I am asking myself whats going wrong here.
Ps.:
I know that I added the "test" as Username and "test" as password - its just to test. Even when the input is the right the error is always the same.
Okay, so I got a response and now I know why this is not working as expected.
loginWithPassord may only be executed on the client.
When you use Meteor.methods on the client, it will still run the functions you define within it on the server. That is why it won't work to have the loginWithPassword call within a Meteor.methods function.
Simply use this function anywhere else on the client. For example - directly within some template event.
Took me like forever to find out why it wasn't working.
Make sure that autoform is actually passing the correct values. If you've made a mistake in you're schema setup it will automatically clean the values (set to undefined) without throwing an error.
I'm also not entirely sure if using it with method set will work in this case, as you want to do the login call on the client not the server (I think).
Make sure your current Meteor instance has an active connection with the mongo database pointed to by variable MONGO_URL. Meteor.loginWithPassword fails to give error feedback when this connection gets closed or broken.

ReferenceError, meteor

I've seen this problem posted but did not really understand the explanations. I am new to meteor and doing this project. From what I understand some of the functionality with node is not available in the browser, but I am unsure of how to fix the problem. I have tried to wrap the code within some function(window) but still was not able to get it working. I also tried to use npm but was coming up empty with some errors about some Illegal tokens. Thanks for any help.
Your app is crashing. Here's the latest log.
/home/alex/TacticsTrainer2/.meteor/local/build/programs/server/boot.js:186
}).run();
^
ReferenceError: window is not defined
at app/js/bootstrap.min.js:6:353
at app/js/bootstrap.min.js:8:3
at /home/alex/TacticsTrainer2/.meteor/local/build/programs/server/boot.js:155:10
at Array.forEach (native)
at Function._.each._.forEach (/home/alex/.meteor/tools/5bf1690853/lib/node_modules /underscore/underscore.js:79:11)
at /home/alex/TacticsTrainer2/.meteor/local/build/programs/server/boot.js:82:5
=> Exited with code: 8
=> Your application is crashing. Waiting for file change.
It looks like you may have not structured your app correctly. You have code that is intended to run on the client/browser side that is running on the server side.
In your app:
place all code to be run on the client in the /client directory
place all server side code in the /server directory
place code that you want to run on both the server and client in the root folder or a non reserved name (public, private, tests, server or client)
For more details about this see the meteor docs: http://docs.meteor.com/#structuringyourapp
ReferenceError is a Node error. Meteor is a framework on top of Node.
Node has a global scope (aka Node's global variable). This error is thrown by Node (not Meteor) if you try to access an undefined global variable.
Browsers also have a global scope called window, and do not throw ReferenceErrors when undefined variables are accessed.
Here's a pattern I like for adding functionality to a class (it's very Meteor):
/lib/Helpers.js <-- Helpers for everyone (node+browser)
/server/Helpers.js <-- Server helpers (node)
/client/Helpers.js <-- Client helpers (browser)
Consider these implementations:
// /lib/Helpers.js
Helpers = {/* functions */}; // Assigned to window.Helpers and global.Helpers
// /server/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}
// /client/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}
This is a trivial example. What if I didn't want to worry about load order? Why not _.extend() in /lib/Helpers.js?
// /lib/Helpers.js
// Helpers = {/* functions */}; // Overwrites...
Helpers = _.extend(Helpers, {/* functions */}); // ReferenceError
Because you'll get a ReferenceError from Node if Helpers isn't defined - specifically the "Helpers" used as an argument. (Node knows to assign Helpers as global.Helpers).
Here are two ways to "fix" this:
1) Assign Helpers to something
// /lib/Helpers.js
if (typeof Helpers === 'undefined') Helpers = {};
Helpers = _.extend(Helpers, {/* functions */});
2) Use helpers from the global
// /lib/Helpers.js
Helpers = _.extend(global.Helpers, {/* functions */}); // works in node, but...
Both of which suck.
1)'s syntax is horrible.
2) works in node, but there is no global in browsers. So it fails it's purpose.
So I gave up and went back to overwriting it the first time in lib, and looking for runtime errors if anything was overwritten.
If you have a handy cross-browser syntax for this, do comment :-)
I think you are calling a method that is loaded on the client and server.
You could write the code inside the Meteor.method like this:
if (!this.isSimulation) {
// code with node js that should only run in the server
} else {
// code that doesn't have nodejs runtime (browser)
}
This happens when you loaded the Method both in the client and server.

Meteor Call Server Method in Client Got 404 Method Not Found Error

I am new to meteor and running to an issue trying to call a server method on the client.
// Client code
Template.email.events({
'click #test-button' : function(e, t) {
Meteor.call('testMethod', function(err, response){
if (err) {
alert("error: "+ err)
} else{
alert("success")
}
});
}
})
// server code
if (Meteor.isServer) {
Meteor.methods({
testMethod: function () {
return "success";
}
});
}
When I click on the button, I got a Error: Method Not Found 404. I tried to put the server method inside Meteor.startup and still gets the same error.What am I missing?
It looks like your code is only running on the client side. Move the block inside the if (Meteor.isServer) to a javascript file in the /server directory of your project.
Code inside the /client directory wont run on the server at all, so Meteor.isServer would always be false and the method would never get created on neither the client or server
Put the Meteor.methods({...}) out of Meteor.isServer() then Meteor will detect you methods.
Plus put the methods on server side (server root folder), I notice that the alphabetical names its important to load three calls method.
I had the same problem when I had the next structure
server
|----- dht-setup.js
|----- methods.js
Then, dht-setup dont see the methods.js methods. Instead, I change the name of the file:
server
|---- _methods.js
|---- dht-sensor.js
The 404 Not found, fixed. The same issue I found in client side when a want to separate functions from templates, for example, separating D3js functions from the templates. You probably need ensure top of the alphabetical load using "underscore" character "_".
Consider that, cause the examples work fine cause the methods are defined in STARTUP.JS, at leat alphabetical word.

yepnope's complete callback question

I am using a "2-step view", where I have a layout template (common for all pages) with yepnope's load (in the html head) of jQuery and some plugins. Something like:
yepnope(['/path/to/jquery.js', '/path/to/jquery.plugin-common.js']);
Sometimes I need another plugin, so within the inner template I do additional (in the html body):
yepnope('/path/to/jquery.plugin-additional.js');
Now that I need to do the actual js magic, can I safely do just:
yepnope({
complete: function(){...}
});
So, the questions are in fact two:
Is the complete callback fired upon the load completion of the global resources stack? So it's safe to "register" this complete callback anywhere assuming that all needed resources have been registered before?
Can I safely call yepnope just with the "complete" callback option? I mean, as long as I'm not "testing" anything and my resources have been registered already...
I have tried it and it worked, but I'm not fully aware if it's internals, so I just want to make sure that I'm not doing something wrong... Thanks in advance.
--
And one last thing. The manual under preload! says:
yepnope({
load: 'preload!jquery.1.5.0.js',
callback: function (url, result, key) {
window.jQuery; // undefined (but it's cached!);
}
});
Can you please explain what is this about? I am completely missing the point here...
I can help on the preload! question.
The idea of preload! is that yepnope will download the file but will not execute it.
It transfers the jQuery file, but it will still be undefined after callback is being called, as it was not injected as a script into the page.
In my opinion, you are doing this wrong. I'm surprised that it work, but maybe your scripts are loaded before the call of the "complete" function. I think you should do that:
yepnope({
load: ['/path/to/jquery.js', '/path/to/jquery.plugin-common.js']
callback: {
"jquery.js": function () {
console.log("jquery loaded!");
},
"jquery.plugin-common.js": function () {
console.log("plugin loaded!");
}
}
});
And for the additional plugin in the html body:
yepnope({
load: '/path/to/jquery.plugin-additional.js'
callback: function () {
$(document).ready(function(){
console.log("plugin-additional loaded!");
});
}
});
Of course, replace console.log() by your code related to each plugin that you can safely execute in this context.
for the last question, i can't say anything, because i didn't succeed to make preload! working, maybe it's buggy, maybe i didn't understand how it work...

Resources