简体   繁体   中英

How to update objects in an array when target field name is in a variable?

I am really struggling to find a way to structure the data that will allow updates that is light on the server.

On the UI, a user clicks add that inserts an object with no values.

Meteor.methods({
addExp: function() {
    var expDoc = {
        objId: new Mongo.ObjectID,
        field_one: " ",
        field_two: " ",
        field_three: " "
    };
     var newExpId = Meteor.users.update({_id:this.userId}, {$addToSet: {'profile.experiences': expDoc}});
     return newExpId;
}
});

Now, using the spacebars #each block helper in the template, the input fields appear and their value attribute is assigned to these fields.

{{#with currentUser.profile}}
    {{#each postcards}}
        <input data-name="field_one" id="one" value="{{field_one}}" type="text">
        <input data-name="field_two" id="two" value="{{field_two}}" type="text">
        <input data-name="field_three" id="three" value="{{field_three}}" type="text">
    {{/each}}
{{/with}}

What I am struggling to do is send an update on keyup to the specific field. As the user may add more postcards to this array, I dont know how to target the specific field to update.

On click event, I can get the target field I want because I put this data in the data-name attribute within the input element var specificField = $(event.target).attr("data-name");

I was given a solution yesterday mongodb query field in object that is being edited but can not get this to work.

Is there another way for me to structure the data that makes updates easier? The update functionality will be like meteor create --example todos but they have one document and one field, so this is easy. But I need more fields other than the 'text' field?

在此处输入图片说明

Ultimately, I am trying to get a user to insert into a form with three input elements. Each element projects the current data of the particular field of that particular object.

Successful operation! Solution: store the field name and value as an object! I stored the data inside a Profiles collection and managed the update on keyup for specific fields to that particular object.

I stored the field name in an object. The value of the input/textarea in focus is stored in a variable. The Session stores the id of the doc when the user focuses on the input/textarea field.

HTML:

{{#each experiences}} // helper to retrieve the docs from Collection
<input data-name="field_one" id="one" value="{{field_one}}" type="text">
<input data-name="field_two" id="two" value="{{field_two}}" type="text">
{{/each}}

client.js

'focus input[type=text], focus textarea[type=text]': function(event) {
 Session.set('DOCID', this._id);

This is the event that calls the update method every 5 seconds on keyup.

  'keyup input[type=text], keyup textarea[type=text]': _.throttle(function(event) {
    var data = event.target.value;
    var specificField = $(event.target).attr("data-name");
    var keyVal = {};
    keyVal[specificField] = data;
    var docId = Session.get('DOCID');
    Meteor.call('updateExp', docId, keyVal);
  }, 5000),

the method: server.js

  updateExp: function(docId, keyVal) {
    Experiences.update({_id: docId}, {$set: keyVal});
  } 

If you decide to store the objects within an array, the following is how you do it. Example: storing the objects inside of an array called 'experiences' in Meteor.user().profile.experiences.

HTML:

{{#with currentUser.profile}}
{{#each postcards}}
<input data-name="profile.experiences.$.field_one" id="one" value="{{field_one}}" type="text">
<input data-name="profile.experiences.$.field_two" id="two" value="{{field_two}}" type="text">
{{/each}}
{{/with}}
// notice the path and positional operator within the data-name. The positional $ operator 
//will act as a placeholder for the first element (our objId) that matches the query document. The event handler will store the data-name into an object for the update operation.

client.js

'focus input[type=text], focus textarea[type=text]': function(event) {
 Session.set('DOCID', this.objId); 
}

objId is the field where the Mongo.ObjectID() is stored. (ref code in question)

The keyup event handler remains the same.

However, the method is different.

server.js

updateExp: function(docId, keyVal) {
Meteor.users.update({_id: this.userId, 'profile.experiences.docId': docId }, {$set: keyVal});
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM