I'm trying to reactively populate my kendo datasource in my
this.autorun(function(){
datasource.data(Organizations.findOne(thisOrg.data._id));
});
which fires properly each time the view is initially rendered, but upon a subsequent template view (not initial render) I get this error in the console which shows that template.data is not loaded for some reason:
TypeError: Cannot read property '_id' of null
at null.<anonymous> (org.js?0330655fbd63766e034cecb907e93089ccc3ef11:129)
at view.js:191
at Function.Template._withTemplateInstanceFunc (template.js:437)
at view.js:190
at Object.Blaze._withCurrentView (view.js:523)
at viewAutorun (view.js:189)
at Tracker.Computation._compute (tracker.js:294)
at new Tracker.Computation (tracker.js:210)
at Object.Tracker.autorun (tracker.js:533)
at Blaze.View.autorun (view.js:201)
Any ideas? I'm banging my head here. Thanks for any input.
It probably means that you have a race condition where the new data is added after the autorun fires. Try to check it has been inserted first:
this.autorun(function(){
if (newDataId === thisOrg.data._id) {
datasource.data(Organizations.findOne(thisOrg.data._id));
}
});
where newDataId is the id you are targeting . You then need to have previously stored the id in the newDataId where you do your insert or method call.
Quick sidenote: I advise to store it in a pageSession variable (reactive var or reactive dict) rather than in a Session var (in order to avoid overcrowding Session).
Related
I have a blaze template like this:
{{>jobsheetsTable companyId=companyId}}
In the JS for the template I have the onCreated function like this ...
Template.jobsheetsTable.onCreated(function(){
const instance = this;
instance.companyId = new ReactiveVar();
console.log(instance, instance.data, instance.data.companyId);
if(instance.data.companyId){
instance.companyId.set(instance.data.companyId);
}
}
The issue is that in the console.log statement I notice something odd ...
instance is correctly outputting the instance with the data object and a companyId
instance.data however returns {companyId: undefined}.
I am not changing instance.data anywhere and the function being passed into this template does not change the companyId.
Update: Using meteor 1.6.1.
The onCreated callback is only run once per template creation, so the data you get is the one that is provided to the initial creation (likely with you attribute set to undefined).
It is likely that the data context is changed after the initial rendering, and this does not trigger the function. as the template is not re-created.
If you are certain that you want to track the data context in the onCreated callback, you need to set a reactive dependency on it, using the Template.currentData() reactive data source. Since it needs to be inside a reactive context in order to be re-run when the data changes, you will need to create one, and a convenient method of doing so is via this.autorun(), which stops the computation for you when the template is destroyed.
Template.jobsheetsTable.onCreated(function(){
this.companyId = new ReactiveVar();
this.autorun(() => { // creates a reactive computation
const data = Template.currentData(); // creates a reactive dependency
console.log('data context', data);
if(data.companyId){
this.companyId.set(data.companyId);
}
})
});
The code above contains an autorun block that will re-run whenever the data context changes.
I am getting a curious error in a template helper and I was hoping someone could lay eyes on it with me. Basically the error I'm getting in the console of the client is that the getArena().height is undefined. However, console.log(getArena().height) returns the correct property value. It appears to be a timing issue causing me to get the error, but my application is actually working. What can I do to alleviate this console error?
//My template helper function
yGrids: function() {
console.log(getArena);
console.log(getArena().height);
var yArray = [];
for (var i=0;i<(getArena().height);i++){
yArray.push({});
}
return yArray;
},
// The console results
function getArena() { // 50
return Arenas.findOne(Session.get('arena_id')); …
Exception in template helper: TypeError: Cannot read property 'height' of undefined
at Object.yGrids (http://localhost:3000/app/app.js?hash=c17abf51d6af6541e868fa3fd0b26e34eea2df28:94:35)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2994:16
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1653:16
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3046:66
at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3687:12)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3045:27
at Object.Spacebars.call (http://localhost:3000/packages/spacebars.js?hash=65db8b6a8e3fca189b416de702967b1cb83d57d5:172:18)
at http://localhost:3000/app/app.js?hash=c17abf51d6af6541e868fa3fd0b26e34eea2df28:24:22
at .<anonymous> (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2754:17)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1875:20
function getArena() { // 50
return Arenas.findOne(Session.get('arena_id')); …
2
This is a very common issue in Meteor helpers when referring to a collection which may not yet have been loaded via a subscription. In general you want to show a loading template instead of your actual layout until your subscription is ready. Or (less elegant) you can defend yourself with:
var arena = getArena();
var height = arena && arena.height;
Whatever getArena() returns you ought to store it in the reactive variable by setting the reactive variable and you can access the reactive var in helper by get() method
My code sometime work and some time won't work
Mongo didn't update sometimes...
But his code is work perfact
What am i do wrong?
Here is my code
http://checkboxploblem.meteor.com
https://github.com/codepawn/practice_makes_perfect/tree/master/checkbox_mongo
origin is
https://github.com/EventedMind/class-build-a-multi-page-app-with-iron-meteor-6737880d
Your problem lies in your event within the 'home.coffee' file:
Template.Home.events
'click [name=isDone]': (e, tmpl) ->
id = #_id
isDone = tmpl.find('input[name=isDone]').checked
Todos.update {_id: id},
$set:
isDone: isDone
You are assigning the first checkbox value to the variable isDone. Thus, if you check the first input box, that is what gets applied to every subsequent task.
You can get around this by retrieving the value of the checkbox from the event object. ie. e.currentTarget.checked
Another alternative is use a unique id for each checkbox and retrieve the value using that id
I'm using Meteor 0.6.5 and I'm trying to publish/subscribe to data that has a specific _id, but it doesn't seem to be successful. The autopublish package has been removed. Below is my code:
Meteor.publish("currentBook", function(bookId){
return Books.find({_id: bookId});
});
Meteor.subscribe("pages", {_id: Session.get("currentBook").id});
Here is the log output from the Chrome console and it does not contain the object I'm looking for:
LocalCollection.Cursor
_transform: null
collection: LocalCollection
cursor_pos: 0
db_objects: null
limit: undefined
reactive: true
selector_f: function (doc) { // 562
selector_id: undefined
skip: undefined
sort_f: null
__proto__: Object
Please let me know how I could resolve this. Thank you
Code:
Meteor.publish("currentBook", function(bookId){
return Books.find(bookId);
});
Deps.autorun(function(){
Meteor.subscribe("currentBook", Session.get("currentBook").id);
});
Publish and subscribe channels must have the same name.
You've wrapped _id in an object in the subscribe channel, but didn't extract it in publish. This wrapping is not necessary.
You should wrap subscribe call in Deps.autorun if you use parameters that can change, like a session variable.
The other thing in addition to Hubert's answer is that using .find() doesn't return the object straight, it returns a lazy cursor which is what you're seeing.
To get the data boxed up into arrays use .find().fetch() when peering in with the console.
I'm doing a simple insert into a meteor collection that appears work, but leaves the collection empty.
The collection is defined properly on the server:
Meteor.publish("comments", function () {
return Comments.find();
});
Subscribed to properly in the client.js:
Meteor.subscribe("commments");
And set up properly on the model.js:
Comments = new Meteor.Collection("comments");
The insert code is as follows:
Meteor.methods({
addComment: function (options) {
check(options.post_id, String);
check(options.comment, NonEmptyString);
if (! this.userId)
throw new Meteor.Error(403, "You must be logged in to comment.");
if (options.comment.length > 1000)
throw new Meteor.Error(413, "Comment is too long");
var post = Posts.findOne(options.post_id);
if (! post)
throw new Meteor.Error(404, "No such post");
// add new comment
var timestamp = (new Date()).getTime();
console.log('Comment: ' + options.comment);
console.log('Post: ' + options.post_id);
console.log('UserId: ' + this.userId);
var saved = Comments.insert({
owner: this.userId,
post_id: options.post_id,
timestamp: timestamp,
text: options.comment});
console.log('Saved: ' + saved);
}
});
Once the insert is called, the console prints out the following:
Comment: Something
Post: xRjqaBBEMa6qjGnDm
UserId: SCz9e6zrpcQrKXYWX
Saved: FCxww9GsrDsjFQAGF
> Comments.find().count()
0
I have inserts into several other collections that work just fine (Posts being one of them as you can see the post ID in the code). In the docs ist said that if the insert errors out it will print to the console, but as you can see it appears to be working, yet is actually empty.
Thanks.
UPDATE: I did find that the data is being put into the database, but for some reason is not showing up. I'm not sure why the data is not being published properly since there are no filters on the find().
I'm not sure exactly what's wrong, but there's a few things to check here.
• First, this:
Meteor.publish("comments", function () {
return Comments.find();
});
directs the server to publish the Collection, but doesn't actually establish the collection server side.
You should have Comments = new Meteor.Collection("comments"); available on both the client and the server. I tend to put in a file called model.js like the examples tend to do.
• Second possibility, you don't have a subscribe function shown above, such as Meteor.subscribe("comments"); If you don't have a subscribe function, your client isn't going to know about it, even though it does exist in the collection.
You can test this theory by typing meteor mongo in the shell (with your Meteor app running), and db.comments.find() to see if your comments are actually in the database but not subscribed to.
Verify you do not have an error in your client code. With Meteor.call, if you do not initialize a variable you can have an error condition that will block reactive updating in your templates but continue to write fine to your console just before hand.
I've made that mistake which I talk about here:
http://doctormehmet.blogspot.com/2013/07/revoltdc-hackathon-20130622-iteration-3.html
Specifically I had something like
Template.mytemplate.helpers({
somevar: function({
if (some_session_var_set_by_a_call.party){
//do something
}
}
Now the somevar function gets called on render, before the Meteor.call returns. Therefore the variable some_session_var_set_by_a_call isn't set yet. The whole thing stops client side on the undefined error.