When I try to call methods inside helpers, reactivity doesn't work. here is my code :
server side method code
Meteor.methods({
getLastContact:function(){
return contacts.findOne({},{sort: {contactID: -1},fields: {contactID:1}})
}
})
client side calling method
Template.createVendor.helpers({
lastIDD: function () {
Meteor.call('getLastContact',function(err,res){
console.log(res.contactID);
}); }});
if some new data is added, template helper losses reactivity and client does not get update.
Can anyone point out what am I doing wrong?
There is a package that makes meteor methods reactive. check out meteor-reactive-method.
It will do exactly what you are trying to do.
When you are calling a method in client helpers you should use
return ReactiveMethod.call("method_name",Parameter1,Parameter2,..);
Include the package for ReactiveMethod call.
Related
I have seen quite a few times that the startup function of Meteor returns a function. What does it mean? Where is the function returned? Who is using the returned function?
Meteor.startup(function () {
Init();
return Tracker.autorun(function () {
const userId = Meteor.userId();
if (!userId) {
//do something
}
});
});
I have not seen startup returning a function, and I have never used it. It wont break and will work all the same, but I do not know why it is done in this example.
It is also strange that it is returning an autorun function... both startup and autorun are client api event handler hooks ... no one should be listening to the results of the function calls becuase these calls are not made by the app but rather the meteor platform, their function is to run code at either startup, or as a separate reactive fiber (autorun).
I understand that Meteor methods let you do a client to server call, but what's the best approach to call another function or method from a Meteor method, i.e. a server to server call.
Right now if I do a regular JS function call it only works if the JS file is in the lib folder. But I need it to be in the server folder.
Here is the code
I have a topics collection which sits in the collection folder and has the following
I have the following which is a collection
Meteor.methods({
topicPost: function(topicAttributes) {
var user = Meteor.user(),
topicWithSameTitle = Topics.findOne({title: topicAttributes.title});
// ensure the user is logged in
if (!user)
throw new Meteor.Error(401, "You need to login to add a new topic");
Meteor.call('checkUser');
}
});
I then have the following method which sits in the server folder
Meteor.methods({
checkUser: function () {
alert('aaaa');
}
});
This works, but it's not a great solution. My method for handling this is to have all of my functions outside the Meteor.methods, and simply relay to the proper functions when necessary.
// Client
Meteor.call('foo');
And:
// Server
Meteor.methods({
foo: function() {
foo();
}
});
foo = function() {
foo = bar;
};
The advantage is that the foo fn can be called from anywhere on the server without a Meteor.call. Meanwhile, Meteor.methods only exposes what is absolutely necessary to the client.
[EDIT] There is some ambiguity as to which 'foo' you're talking about; obviously the server knows you mean the one outside the methods call. But if you're feeling confused, you can always rename one or the other. The advantage to this is that there is minimal refactoring involved.
Just to clarify for readers who don't notice that the OP's code actually contains the answer, you just do
Meteor.call('checkUser');
on the server. Per the meteor docs (https://docs.meteor.com/api/methods.html#Meteor-call), on the server, if you use Meteor.call() without a callback argument, the call runs synchronously and waits for the result. For example, if 'checkUser' was written to provide a userId value, you'd just do
let userId = Meteor.call('checkUser');
On the client, though, you have to provide a callback function as an argument to Meteor.call(), and the userId would be provided asynchronously to your callback function.
So I have already written a fairly large app in meteor but just adding minimongoid package to it. I have figured out it likes first() rather than findOne(), create() rather than insert(), but I can't figure out how to update a document. I am trying to do the following, but it shows the error below... What am I doing wrong?
Transactions.update {_id: txn._id},
$set:
"isActive": false
TypeError: Object function Transactions() {
I20140302-18:22:54.226(-5)? return Transactions.__super__.constructor.apply(this, arguments);
I20140302-18:22:54.226(-5)? } has no method 'update'
All I have in my postings.coffee is
class #Transactions extends Minimongoid
#_collection: new Meteor.Collection('transactions')
With minimongoid you update object instances rather then with Class methods.
Something like this:
aTransaction = Transaction.create({-some attributes-})
aTransaction.update({attributeName: attributeValue})
I am still new to MeteorJS but let me try. This took a while before I figured out on my own. Good thing we use RoR at work. What I am going to do is something like:
on server JavaScript: (If you use Rails, this should be easy to get.)
Meteor.methods
updateTransaction: (id, name, url) ->
Transaction.find(id).update(
"isActive": status
)
then on my client JavaScript (template):
Template.transaction_template.events
'submit .transaction-form': (event, template)->
event.preventDefault() // if using an <a>, remove is using button with type=button
status = template.find('[name=status]').value // find the input form with the name=status
Meteor.call 'updateTransaction', { id: #_id, status }
When trying to render my template, i want to load the data from the server. I'm trying to use Meteor.call but as per the documentation, i'm clearly not in a stub.
If I use Meteor.call inside of an event handler, the response i get back is correct. If i call it within the template.created or similar, i get an undefined response. I guess i could use async call to do it and then render it when available. But is there another way?
I don't want the clients to have direct access to the DB, i want it to come from the server.
//This doesn't work
Template.config.created = function() {
console.log(Meteor.call('getValue')); //returns undefined
};
//This works
Template.config.events({
'blur #button' : function () {
console.log(Meteor.call('getValue')); //Prints value
}
Any clues?
D
You need to use a callback in your Meteor.call
Template.config.created = function() {
Meteor.call('getValue', function(error, data) {
if(error){
//do stuff to handle error
}
console.log(data);
});
};
From the docs:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
I'm not sure why your event handler call is working... There isn't any way to synchronously get a server response like that in JavaScript without Fibers. The solution is simply to provide an asynchronous callback. This isn't really a Meteor limitation, it's just a JavaScript limitation.
I would like to use the GetLocalizedItems method in the Anguilla Framework.
I don't know how to create a new filter and set the conditions or what to use for success and failure.
In the GUI:
tridion.Web.UI.ContentManager.WhereUsed.GetListUsedItems(id, filter.conditions,
filter.columns, success, failure);
Are the methods in this namespace intended to be used by our extensions?
Building a filter
Here is an example of how to build a filter
var filter = new Tridion.ContentManager.ListFilter();
filter.conditions.ItemTypes = 16 | 2; // folders and components
filter.conditions.Recursive = true;
filter.conditions.BasedOnSchema = "tcm:1-23-8,tcm:1-32-8".split(",");
filter.columns = Tridion.Constants.ColumnFilter.DEFAULT;
Or this extremely simple case from General.js:
var templateFilter = new Tridion.ContentManager.ListFilter({
conditions: { ItemTypes: [ itemType ] }
});
Calling a WCF method
The second part of your question was really already covered in https://stackoverflow.com/a/9385975/209103, although I'll make it a bit more concrete here.
WCF/AJAX calls such as this are executed asynchronously, since they may take some time to complete. While you would normally simple handle the result of the call on the line after the closing parenthesis, you can't do that in AJAX calls since that line will be execute before the function has completed. Instead you have to pass in one or more callback functions that get called once the function completes.
I typically just pass in two functions that break into the JavaScript debugger of my browser when I first start figuring out such a method:
Tridion.Web.UI.ContentManager.WhereUsed.GetListUsedItems(
"tcm:1-23",
filter.conditions,
filter.columns,
new function() { console.log(arguments); debugger; },
new function() { console.log(arguments); debugger; }
);
So the first (anonymous) function is called when the (asynchronous) HTTP call to the TCM server succeeded, while the second is called when the call failed. In the answer I linked above, we called them onSuccess and onFailure to make their nature more explicit.
Both functions in this case simply write the implicit arguments parameter that is always passed in JavaScript. They then break into the JavaScript debugger of your browser, so you can inspect the arguments further.