Meteor - autoform - Non-Collection

meteor-autoform

Can we use autoform with non-collection stuff?

Yes. If you want to use an AutoForm for a form that does not relate to a collection (like a simple contact form that sends an e-mail), or for a form that relates to a collection that is schemaless (for example, Meteor.users()), you can do that.

  1. In client+server code, create a SimpleSchema instance to define the form's schema.
  2. Use the SimpleSchema instance as the schema attribute of autoForm or quickForm.
  3. Set up the form to be submitted properly. There are three ways to handle this:
    1. Define an onSubmit hook for the form. Put your logic in that function and have it return false to prevent normal form submission.
    2. Add normal form attributes like action and let the form do a normal browser POST after being validated.
    3. Define a server method that does something with the form data. On your autoForm or quickForm set type="method" and meteormethod="yourServerMethodName".

When you use the third option, a server method, the form data will be gathered into a single object when the user clicks the submit button. Then that object will be cleaned and validated against the schema on the client and passed along to your method on the server. You must validate it again in your method on the server, using check() in combination with myAutoFormSchema. This is why we create the SimpleSchema instance in client+server code.

It's also generally best to call myAutoFormSchema.clean for the object again in the server method. In particular, you will definitely want to do this if the object's schema has auto or default values so that they can be added securely and accurately on the server.

An Example Contact Form:

// common.js:
Schema = {};
Schema.contact = new SimpleSchema({
    name: {
        type: String,
        label: "Your name",
        max: 50
    },
    email: {
        type: String,
        regEx: SimpleSchema.RegEx.Email,
        label: "E-mail address"
    },
    message: {
        type: String,
        label: "Message",
        max: 1000
    }
});

Note that we've created an object Schema in which to store all of our app's schemas.

// HTML:
<template name="contactForm">
  {{#autoForm schema=contactFormSchema id="contactForm" type="method" meteormethod="sendEmail"}}
  <fieldset>
    <legend>Contact Us</legend>
    {{> afQuickField name="name"}}
    {{> afQuickField name="email"}}
    {{> afQuickField name="message" rows=10}}
    <div>
      <button type="submit" class="btn btn-primary">Submit</button>
      <button type="reset" class="btn btn-default">Reset</button>
    </div>
  </fieldset>
  {{/autoForm}}
</template>

// client.js:
Template.contactForm.helpers({
  contactFormSchema: function() {
    return Schema.contact;
  }
});

// server.js:
Meteor.methods({
  sendEmail: function(doc) {
    // Important server-side check for security and data integrity
    check(doc, Schema.contact);

    // Build the e-mail text
    var text = "Name: " + doc.name + "\n\n"
            + "Email: " + doc.email + "\n\n\n\n"
            + doc.message;

    this.unblock();

    // Send the e-mail
    Email.send({
        to: "test@example.com",
        from: doc.email,
        subject: "Website Contact Form - Message From " + doc.name,
        text: text
    });
  }
});

Note the call to check(), which will throw an error if doc doesn't match the schema. To reiterate, you must call check() in the method or perform your own validation since a user could bypass the client side validation. You do not have to do any of your own validation with collection inserts or updates, but you do have to call check() on the server when submitting to a Meteor method.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License