This._id returning undefined


#1

Hi,

I’m new to meteor and trying to understand this._id. I have a Weights collection that I’d like to update, but the this._id is returning undefined.

html:
<template name="weight"> <h4>Your weight is:</h4> <h4 id="textArea" class="editable" data-type="textarea" data-placeholder="Enter Weight" data-emptytext="Click to enter weight" data-rows="4">{{weight}}</h4><br/> </template>

js:
Template.weight.rendered = function() { $('#textArea.editable').editable({ success: function(response, newValue) { console.log(this._id); Weights.update(Session.get("newWeight"), {$set: {weight: newValue}}); } }); }

Why does this._id return undefined? Thanks!


#2

In rendered function this refers to the template itself. Try this.data._id. Also just debug and you will see yourself.


#3

is this.data._id only for Iron Router? I tried it for a similar problem and it still returned undefined for me (app is using Flow Router).


#4

Just debug, set a breakpoint in your rendered function, and check what you get. Try with different data contexts (#with, #each or simply pass data when including your template {{>yourtemplate yourData}}. It shouldn’t be related to a router as far as i know.


#5

I didn’t ever get any form of this.data._id to work.

After a lot of tinkering, this works - my question was similar and may not be quite what you’re looking for, but I hope it helps.

var getField = myCollection.findOne({});
console.log(getField.myFieldName);

EDIT:
This only loaded the correct field once (I’ve now tried so many things, I forgot where I put it, but I think it was in the template’s js onRendered statement). Subsequent access of the template for different _id’s still persisted the field from the originally loaded _id. Since this worked only on the first load of the template, it’s not a good solution.


#6

Hey Deborah,

Within your rendered (or onRendered) function, this.data will refer to the template’s data context (if it’s ready). The reason that this.data._id wasn’t working for you is because you were trying to access it within a jQuery callback function:

success: function(response, newValue) {
    console.log(this.data._id);
    ...

Within this callback, this does not refer to the template instance. We actually have no idea what this refers to; it depends on how the editable jQuery plugin decided to call the success function.

There are a couple of ways of dealing with this. The slickest is to use the new ES6 function syntax, which will bind the function’s this to the context where it was defined. So if you change your callback to something like this, it should work:

success: (response, newValue) => {
    console.log(this.data._id);
    ...

Now this in the success callback will refer to the template instance, so we can grab the data context and the _id. Note that _id may still be undefined if the data context isn’t ready yet… But that a whole other can of worms.


#7

Hi everyone,

Thanks for the response. I had tried several different combinations (like this.data._id) with no success. I tried the new ES6 function syntax, however, this didn’t work for me.

I was able to get it working with this though:

js:
console.log($(this).data("pk"));

html:
<h4 id="textArea" class="editable" data-type="textarea" data-pk="{{_id}}" data-value="{{weight}}" data-placeholder="Enter Weight" data-emptytext="Click to enter weight" data-rows="4">{{weight}}</h4><br/>


#8

Hi spyko, I’m trying that but am unsure of the right part of the js to try it in. In template helper? In onRendered? If in onRendered, doesn’t it persist the originally loaded _id even when template is accessed with a different _id?

Where in the js did you get it working? I would love to get this solved too.


#9

Hi Deborah,

I have the following:

js:
Template.weight.rendered = function() { $('#textArea.editable').editable({ success: function(response, newValue) { console.log($(this).data("pk")); // this._id is the id of the new weight input by user Weights.update($(this).data("pk"), {$set: {weight: newValue}}); } }); }

And I use the html code from the previous post to call the above template. I’m still running into some issues with inserting when the database is empty, but this works when updating a current value in the database. Hope this helps!


#10

It does help. Thank you!

I have some similar questions right now on Stack Overflow and one also on this forum. I’ll return here and update if a better solution emerges.

Links to similar issue where this.collectionFieldName in template.js returns null or undefined…


#11

Hi spyko.

I don’t know how you’ve set up your subscriptions and data context for you template. But I presume that your writing your application according to the Meteor Guide (subscribing in a template and passing the data to sub templates)

I would start by binding your template instance to a variable and try something like this:

Template.weight.onRendered({
    var instance = this;
    $('#textArea.editable').editable({
        success: function(response, newValue) {
            console.log(instance.data._id);
            Weights.update(instance.data._id, {$set: {weight: newValue}});
        }
    });
});

What happens when you try this?

If it gives you an error about data._id being undefined I suspect that you’re trying to render this template before the subscription is ready?