Using the same form for creation and editing


#1

Hi, using Blaze, new at webdev.

I have a form that is being used to insert data into a new Mongo document. I want the user to also edit the document using the same form. What is the pattern I should use for this?

Is it normal to read the form values directly from the DOM after the submit form event, or is that considered an anti-pattern and instead I should always use the target data from the form submission data?

Thanks


#2

Are you using React by any chance? With React, it can be helpful to put the variables that will contain each form value, into the state. The form displays the values that are in the state. Then when new values come in, say from a function that loads a previous entry, they are immediately displayed in the form.


#3

Blaze has been a while ago for me, but I was making that decision on my template submit event. The form html was always the same and it includes a hidden field with the document _id. When this field is filled in, my handler would send an update method:

Template.myForm.events({
  'submit #my-form'() {
    const target = event.target;
    const _id = target._id.value;
    const text = target.text.value;

    if(_id) {
      Meteor.call('updateDoc', { text });
    } else {
      Meteor.call('insertDoc', { text });
    }
  }
});

If you are using autoform you could use your template helpers to inject the selected _id into your template and load the appropriate mode like that:

Template.myForm.helpers({
  mode() {
    return FlowRouter.getParam('_id') ? 'update' : 'insert';
  }
});

#4

Thanks. Is it best to populate the data into the form manually myself or to let spacebars handle it?

My thoughts are:

  1. If the form is loaded with an _id param then it will find that object from Mongo, and save the document object as a variable (lets call it state) within the template.
  2. I then populate the form using the object, manually in the onRendered function?
  3. When it comes to insert or update, I read each value in the form submission event target into the state object variable.
  4. I then insert or update the mongo document with the state object.

I think I have to use a manual loader, rather than using spacebars, as I am using some Semantic UI components whose data needs to be populated with javascript calls, rather than using the value attribute.

Again, I am new to all this. Does that sound usual, or am I using a but of an anti-pattern and there is a better way? I know all the newness is React/Vue etc, but I want to just use Meteor/Blaze for now.


#5

I would let spacebars handle it:

Template.myForm.onCreated(function() {
  this.autorun(() => { // Subscribe to the doc here
    this.subscribe('someSubscription', FlowRouter.getParam('_id')); // Fetching _id from the route
  });
});

Template.myForm.helpers({
  doc() {
    return DocsCollection.findOne(FlowRouter.getParam('_id'));
  }
});

<template name="myForm">
  <form>
    <input type="text" name="title" value="{{doc.title}}" />
    <input type="hidden" name="_id" value="{{doc._id}}">
  </form>
</template>

As you can see in the above example, the form is just always the same. All the fancy stuff happens in your helpers and onCreated callback.


#6

I basically was producing so much spaghetti code trying to do what I was trying to do, that I rethought the process.

What I am doing now is creating a barebones document in Mongo as soon as the form is entered, then as the user completes parts of the form I am picking up change events and using an update set command to push that into the client minimongo instance, then letting Meteor do its magic.

This is actually closer to desired functionality so I am very happy.


#7

Interesting approach. Are you removing the doc when the user ‘cancels’ creation?


#8

I have a status field in the Mongo document that is initially set to ‘Draft’. When the user selects the submit button on the form then the document is tested against a SimplSchema, if it passes then the document is allowed to set the document status to ‘Submitted’.

I don’t have a cancel button, I have a little trash button, which sets the status to ‘Trashed’. I will have code that will run every day and if the document has been Trashed for 10 days then it will delete.

Again, I wanted this functionality to be used for creation and editing and this also allows a recycle bin type feature.

This approach is basically using MiniMongo as the state variable holder.