Search code examples
mongodbmeteormeteor-autoform

how to set a trigger to add to a date in meteor using quickform


I have MemberProfiles and MemberPayments collections.The MemberProfile has expiryDate field which is set to current date at insert.I need to extend expirDate of a unique MemberProfile whenever a MemberPayment is added to that MemberProfile.

 MemberProfiles = new Mongo.Collection('memberProfiles');
 MemberProfileSchema = new SimpleSchema({
 expiryDate: {
   type: Date,

   autoValue: function () {

    return  moment().toDate();
    },

    autoform: {
        type: "hidden"
    }
} 

// to insert into Memb erProfiles
 {{> quickForm collection="MemberProfiles" id="insertMemberProfileForm"      type="insert" class="new-recipe-form"}}

 //the code for MemberPayments collection

 MemberPayments = new Mongo.Collection('memberPayments');

MemberPayments.before.insert(function (userId, doc) {

let memberProfile= MemberProfiles.direct.findOne({profile: doc.memberId});

  MemberProfiles.update(doc.memberId, {

    $set: {
         expiryDate: moment().add(31, 'days');
,
     }
 }
)

});

I have added all the necessary packages but still this doesnt work.I am getting error Cannot set property 'expiryDate' of undefined


Solution

  • It is challenging to try and resolve issues like this without having a more complete example of the app or reference to the complete project in github or somewhere else.

    However, when I read through your code I noticed an issue in your MemberProfiles.update() function. I also noticed that it appears you are only processing your form from the client side (e.g. because your quickform is not using a Meteor Method) so you will have to manually call the SimpleSchema .clean() method to generate your autovalue. Keep in mind that your client side approach might work ok now, but once you remove the insecure package you will either have to implement a Meteor Method to perform the insert or configure your collection allow/deny rules to allow client side insert (this is dangerous).

    Since you are using moment.js you need to be careful that you always pull the date from the moment object before storing in mongodb. In this case, you are trying to set expiryDate to the value returned from moment().add(31, 'days') which is just another moment object.

    Also, I would assume you want to add 31 days to the current value of expiryDate, however you are never initializing moment with the expiryDate. Therefore, you will always be setting the expiryDate to 31 days from the time the function executes.

    Lastly, you have a syntax error (; inside your $set object) and your findOne selector includes {profile: doc.memberId} however your MemberProfiles schema says there is only a _id and expiryDate field in your collection.

    Try this new logic that addresses the above issues and see if that resolves your issue.

    MemberPayments.before.insert(function (userId, doc) {
      let memberProfile = MemberProfiles.direct.findOne({profile: doc.memberId});
    
      if (memberProfile) {
        if (!memberProfile.expiryDate) {
          console.log("expiryDate was not previously set!");
        } else {
          MemberProfiles.update({profile: doc.memberId}, {
            $set: {
              expiryDate: moment(memberProfile.expiryDate).add(31, 'days').toDate()
            }
          });
        }
      } else {
        console.log("memberProfile not found");
      }
    });
    

    Now that this is fixed, you need to resolve the issue of your autovalue not being generated on the client side. You do this by calling the SimpleSchema .clean() method. Since you are not using Meteor Methods to process your quickForm (and therefore doing everything client side), you need to add the below AutoForm hook to ensure that the SimpleSchema .clean() method is called before the doc is saved (which will then execute your autovalue logic).

    AutoForm.hooks({
      insertMemberProfileForm: {
        before: {
          insert: function(doc) {
            MemberProfileSchema.simpleSchema().clean(doc);
            return doc;
          }
        }
      }
    });
    

    You should put the above code in the onRendered() callback of the template that creates your quickform (e.g. the template that contains the below code in the HTML).

    {{> quickForm collection="MemberProfiles" id="insertMemberProfileForm" type="insert" class="new-recipe-form"}}