Search code examples
javascriptmeteormeteor-autoform

Meteor autoform - compute value for hidden field


In a meteor autoform (using the classic aldeed package: https://github.com/aldeed/meteor-autoform), I have a hidden field called 'score' whose value is a function of another field called 'optionID'.

{{#autoForm
  class                = "autoform"
  id                   = dataID
  collection           = (getCollection 'DataColl')
  doc                  = dataDoc
  type                 = "method-update"
  meteormethod         = "DataColl.autoformUpsert"
  singleMethodArgument = true
  autosave             = true
}}

  {{> afQuickField
    name         = 'optionID'
    type         = "select-radio"
    template     = "buttonGroup"
    options      = scoreOptions
  }}

  {{> afQuickField
    name         = 'score'
    type         = "hidden"
    value        = selectedOptionScore
  }}

{{/autoform}}

The function selectedOptionScore depends on the selected value of 'optionID' (using Autoform.getFieldValue)

Template.formTemplate.helpers({
  selectedOptionScore(): String {
    const optionID = AutoForm.getFieldValue('optionID');
    const optionScore = someFunction(optionID);
    return optionScore;
  },
});

The problem is that on each autosave of the form, the value of 'score' is "one change behind" the value of 'optionID', meaning the function computing 'score' is correct, but the save to mongo seems to have happened before the 'score' value was updated, so in mongo, 'score' has the value of whatever it was right before 'optionID' last changed.

For example, if I make 'score' not hidden such that I can modify it, modifying it directly in the webpage will make its value reflected correctly in mongo. But modifying 'optionID' in the webpage yields the "one change behind" behavior.

Is there a way to make a meteor autoform field depend on another field in the same form, without having it "lag behind" the autosave by one change always?


Solution

  • Instead of using a Template helper to calculate the value of your hidden score field, you might want to look into using a autoform hook. So instead of using your selectedOptionScore Template helper, you would define a hook like:

    AutoForm.addHooks(['your-form-id'], {
      before: {
        method-update(doc) {
          doc.score = someFunction(doc.optionID);
          return doc;
        }
      }
    });
    

    This way just before your form is saved the calculated score is set, and saved with everything else.