[SOLVED] Nested {{#each}} using this._id gives undefined when checking check box control


#1

Ok, I have a set of checkboxes for each row in a grid. I’m trying to get my checkbox to update the MongoDB state with each click (following the tutorial online), but when I console log my this._id i get undefined as the value, and thus it’s not updating in the db.

Am I missing something to get the _id of the checkbox that I’m checking.

        console.log("ID: " + this._id + " | checked state sent: " + !this.checked);
        Meteor.call('Selected.update', this._id, !this.checked);
    }```

Additionally, the `!this.checked` gives true every time.  

As always, I appreciate the help.

#2

There are a couple of things to check.

Your checkbox html must be in its own template. So, not like this:

<template name="list">
  <ul>
    {{#each thing}}
      <li><input type="checkbox"></li>
    {{/each}}
  </ul>
</template>

But like this:

<template name="list">
  <ul>
    {{#each thing}}
      {{> listItem}}
    {{/each}}
  </ul>
</template>

<template name="listItem">
  <li><input type="checkbox"></li>
</template>

And put your event handler against listItem, not list.

Avoid DOM ids

Your event handler is using a DOM id in its selector. This suggests that your checkbox definition looks like <input id="isSelected">, which implies that you will end up with multiple id="isSelected" on the page. This is an anti-pattern - there must be only one id="isSelected" on any page: https://developer.mozilla.org/en-US/docs/Web/API/Element/id

It must be unique in a document…

Having identical ids on a page is known to cause problems in Meteor, so must be avoided - use classes instead: <input class="isSelected">


#3

I believe I have the template part correct, as you’ve shown above, but yes, I am using the same id on each one created I suppose. So that may just be it. I’ll change it to class instead and see if that fixes it.


#4

Ok, I’ve tried what you suggest above, but must still have something wrong. I can’t seem to get my state for the checkbox to change because the _id of the checkbox is still coming through as undefined.

I want to post my code, but it’s quite a bit, i hate to post it embedded. Is there a better way?


#5

Ok, I’ve posted the code at https://github.com/LBBLUG/meteorBastas

If anyone can take a look, and point me in the right direction I would appreciate it.

To help you along, the code I"m having an issue with is in /client/layouts/admin/displayRecipAndGifts/

Thanks for any help,


#6

Hey I’ve looked in to your code, there are few things.

  1. Checked state with blaze is easy, the Template helpers should simply return true or false. Also in HTML loose the commas checked={{isCheckedIn}}.

  2. Meteor uses jQuery to handle events and extends the handling function with the corresponding template.

'click .element'(event, template) {

     event.currentTarget //contains the currently clicked element
     event.target //bubbled up event, great for form submitting!

     this //has the current data scope if generated inside an {{#each}} block or {{#with}}

    const checked = event.currentTarget.checked; //gives you T/F
    const id = this._id; //gives you the _id

}
  1. Rob is actually wrong about not using id with checkboxes, because the browser than can match the checkbox with the respected label like this.

template.html

<input type="checkbox" class="checkbox" id="checkedIn" />
<label for="checkedIn">Checked In</label>

This way, if you click the label, you check the box, also we can go “creative” with JS!

'change .checkbox' (event, template){

    return this[event.currentTarget.id] === "true";
    //if its a boolean you can get away just with the "return this[event.currentTarget.id]"

}

#7

All I said was you can’t use the same id in multiple places on the same page - and it’s not me saying that - it’s w3.org :slight_smile:


#8

ups sorry, you are right about that! :slight_smile:


#9

Hey @davethe0nly,

I appreciate the hints, and I’m getting closer. I’m getting the true false from the click (mostly), but still getting undefined as the _id.

I’ve broken this down into as small component as I can imagine, but can’t seem to get the ID after the table is built. Is it too many layers.

I have a list of recipients, each having 1 or more gifts, and each gift has a set of status (checkboxes). So I completely understand @robfallows point about not using the id attribute on the page, and I’ve switched to using a class on the element, but still when I click the checkbox / switch I get undefined for the _id of the element.

As always any help is appreciated.


#10

do a console.log(this) and check the output :slight_smile:


#11

I’ve created a small repo which illustrates how this should work. Hopefully, it will point you in the right direction. (No apologies for use of insecure and autopublish :slight_smile: ).


#12

Ok, @robfallows, I’ve pulled your repo, and run it, and looked at it, and it makes total sense.

I see where you have a single set of checkboxes per name, and they work.

I thought, ok, I have a single button for each name, let me work on that, and it works just like your example does.

But with each name, I have multiple sets of the same checkboxes stored in an array in Monbo, and when I bring those back I do another {{#each }} for those inside the first {{#each }} that lists out my recipients. Is this ‘compound’ {{#each }} possibly the problem? Because using the exact same code for the checkbox, I still get ‘undefined’ as the _id, while the code on the button click event gives me the _id with no issue for the same recipient.

I know you guys are getting tired of my questions, and I’m frustrated, so I apologize for all this mess.


#13

If you are not in the “outer” template when processing the inner {{#each}} then you will have lost the context of the original document. You could re-introduce the _id (or even the whole context if that’s necessary) if this is the case by adding it into the inner template invocation. Maybe something like this:

{{#each inner}}
  {{> subtemplate _id=_id}}
{{/each}}

or

{{#each inner}}
  {{> subtemplate parent=this}}
{{/each}}

and then referencing this.parent._id in subtemplate's events.

:slight_smile: no worries - happy to help.


#14

I’ve just noticed, you are handling the events in parent template, try getRecipientsAndGiftCheckbox instead of getRecipientsAndGift. If I get a minute, I’ll d/l the repo and take a look.


#15

@robfallows and @davethe0nly

I finally got it. Rob your answer didn’t quite get me there, but it gave me an idea.

So instead of _id = _id, I had to do _id = …/_id (basically tell it to get the ID up one level. Your parent = this prompted that concept.

Now, as Dave said, I’m working on the getRecipientsAndGiftsCheckboxes template, and voila.

Thank you both so much for all of your patience and help!