mongodbmeteorcoffeescriptpugmeteor-autoform

Using one autoForm, I need to insert data into two collections


I am currently working on an inventory system that takes a Part Collection, and a Purchase Collection as the backbone of the application. Each part much have a corresponding purchase. I.E a Part must have a partId, serial number, and cost number associated with it. I am using Meteor.js with coffeescrip, jade, and Graphr. I can insert into each collection individually, but they do not seem connected. I have set up the linkers between the two connection but I am a little lost as to where to go next

here is a snippet of the collections

Purchase Collection

    PurchaseInventory.schema = new SimpleSchema
        partId:
            type:String
            optional:true

        serialNum:
            type:Number
            optional:true

        costNum:
            type:Number
            optional:true

Parts Collection/schema


    Inventory.schema = new SimpleSchema

        name:
            type:String
            optional:true

        manufacturer:
            type:String
            optional:true

        description:
            type:String
            optional:true

parts query


    export getInventory = Inventory.createQuery('getInventory',
        $filter: ({ filters, options, params }) ->
                if params.filters then Object.assign(filters, params.filters)
                if params.options then Object.assign(options, params.options)
                return { filters, options , params }
        name:1
        manufacturer:1
        description:1
        pic:1
        purchase:
            partId:1

    )

purchase query


    export getPurchase = PurchaseInventory.createQuery('getPurchase',
        $filter: ({ filters, options, params }) ->
                if params.filters then Object.assign(filters, params.filters)
                if params.options then Object.assign(options, params.options)
                return { filters, options , params }
        serial:1
        cost:1
        date:1
        warrentyDate:1
        userId:1
        )

Linkers

//Parts
    Inventory.addLinks
        purchase:
            collection:PurchaseInventory
            inversedBy:"part"


    //purchases
    PurchaseInventory.addLinks
        part:
            type:'one'
            collection:Inventory
            field:'partId'
            index: true

And finally the Jade/Pug auto form


    +autoForm(class="inventoryForm" schema=schema  id="inventoryInsertForm" validation="blur" type="method" meteormethod="inventory.insert")
        .formGroup
          +afQuickField(name="name" label="Name")
          +afQuickField(name="manufacturer" label="Manufacturer")
          +afQuickField(name="description" label="Description")
          button#invenSub(type="submit") Submit

To reiterate my goal is to have each item in parts to have a link to its corresponding purchase data.


Solution

  • The most straight forward way is to use autoform form type normal and create a custom event handler for the submit event (alternatively you can use the AutoForm hooks onSubmit). From there you can use the AutoForm.getFormValues API function to get the current document.

    Since I am not into Coffeescript I would provide the following as Blaze/JS code but I think it should give you the idea:

    {{# autoForm type="normal" class="class="inventoryForm" schema=schema  id="inventoryInsertForm" validation="blur"" schema=schema  id="insertForm" validation="blur" }}
      <!-- your fields -->
    {{/autoForm}}
    
    /**
     * validates a form against a given schema and returns the
     * related document including all form data.
     * See: https://github.com/aldeed/meteor-autoform#sticky-validation-errors
     **/
    export const formIsValid = function formIsValid (formId, schema) {
      const { insertDoc } = AutoForm.getFormValues(formId)
      // create validation context
      const context = schema.newContext()
      context.validate(insertDoc, options)
    
      // get possible validation errors
      // and attach them directly to the form
      const errors = context.validationErrors()
      if (errors && errors.length > 0) {
        errors.forEach(err => AutoForm.addStickyValidationError(formId, err.key, err.type, err.value))
        return null
      } else {
        return insertDoc
      }
    }
    
    Template.yourFormTempalte.events({
      'submit #insertForm' (event) {
        event.preventDefault() // important to prevent from reloading the page!
    
    
        // validate aginst both schemas to raise validation
        // errors for both instead of only one of them
        const insertDoc = formIsValid('insertForm', PurchaseInventory.schema) && formIsValid('insertForm', Inventory.schema)
    
        // call insert method if both validations passed
        Meteor.call('inventory.insert', insertDoc, (err, res) => { ... })
        Meteor.call('purchaseInventory.insert', insertDoc, (err, res) => { ... })
      }
    })
    

    Note, that if you need both inserts to be successful on the server-side you should write a third Meteor method that explicitly inserts a single doc in both collection in one method call. If you have Mongo version >= 4 you can combine this with transactions.