Updating Object in Array from #each Loop


#1

Hi all,

I’ve been looking into this a lot, and I’m trying to implement a notes system within a document that can be updated using x-editable. My problem is I can’t seem to be able to get the change to update the database.

I have tried using the $ operator and have searched for hours. I’m reasonably new to Meteor and am yet to be able to figure it out.

‘notes’ is a property in my document I am iterating over using #each, and I need to update specific notes

"notes" : [
            {
                    "title" : "Tarog",
                    "description" : "Unu afejufav tic kobgib kefvotet capi noma ewrekos ut ubbar icodafo tawmuvdif gotib jiebi cesvuwmu fajumpu."
            },
            {
                    "title" : "Mume",
                    "description" : "We ritop fu kevi ene wob lozivdi vibil womazla saob nut sojade jet."
            },
            {
                    "title" : "Gupgaf",
                    "description" : "Gompaphug zosku wo tocca rif hab cuvlipve hi fig ugadiche lecrup zakija."
            },
            {
                    "title" : "Sesekepo",
                    "description" : "Mockus beud bor fahab hi cepmu du wunefepe piibpup bavcan solpojol ug dajsuni was wob hinar omtigra."
            },
            {
                    "title" : "Ej",
                    "description" : "Waapvi par jid pa bo vim vawvekra huwbuprup amoil ohu ihdeni zahgipri oseruful danaru."
            }
    ]

Currently my JS:

Template.viewJob.onRendered(function () {
    $('#textArea.editable').editable({
    success: function (response, newValue) {
        Jobs.update(
            {"_id": parentID},
            {
                "$set": {
                    'notes.$.title': newValue
                }
            }
        )
    }
})
});

And this is the each loop:

{{#each notes}}
  <div class="well">
    <h3 class="whichIndex">{{title}}</h3>
      <p id="textArea" class="editable" data-type="textarea" data-mode="inline" data-placeholder="Enter text"
               data-emptytext="Click to enter text" data-rows="4">{{description}}</p>
  </div>
{{/each}}

Help would be greatly appreciated!


#2

Where is your parentID variable set?


#3

There are kind of a lot of things going on here.

  1. You are looping through your notes and creating duplicate <p> tags with the same id.
  2. Your parent template (viewJob) will likely trigger the onRendered call before all of the children (notes) are rendered, so your $.editable function may not apply to all of the elements you expect.
  3. The syntax for updating a specific note – in this case, the first note – $set: { 'notes.0.title': newValue }

Can you share the rest of your template code?


#4

Currently I’ve just declared parentID at the top of the file, assigning this._id in a helper.


#5

Hi.
Rest of my js: http://pastebin.com/2HGxsude
Rest of my Template: http://pastebin.com/APE3pEeg

I can get it to work with other properties…but not an array of objects.

Try not to cringe too much…I’m new to this.


#6

No worries, everyone starts somewhere and sharing code is always nerve-wracking, even when you think you know what you’re doing, haha.

So first, I’d move things around so you know your onRendered is firing correctly and drop the id, as you don’t really need it. Also, note the data-index="{{@index}}", which will allow you to access the element’s index for your update.

{{#each notes}}
  <div class="well">
    {{> note}}
  </div>
{{/each}}

<template name="note">
  <h3 class="whichIndex">{{title}}</h3>
  <p class="editable textArea" data-type="textarea" data-mode="inline" data-placeholder="Enter text" data-emptytext="Click to enter text" data-rows="4" data-index="{{@index}}">{{description}}</p>
</template>

Then, move your onRendered into the note template, and make a few adjustments. You can use a class selector instead of the id. And since you will need to access the data properties of your element, you won’t use success, but rather the ‘save’ event.

Template.note.onRendered(function () {
  this.$('.textArea.editable').on('save', function(e, params) {
    var noteIndex = e.currentTarget.dataset.index;
    Jobs.update(
      { _id: parentID },
      { $set: 
        { 'notes.' + noteIndex + '.title': newValue }
      }
    );
  });
  this.$('.editable.textArea').editable();
});

Let’s see if this gets you closer?