0

I am following this tutorial to create a form in my project, which is leveraging the Apostrophe CMS. When i follow the tutorial, I am able to create the form and submit, and understand how to view the form submission in the Admin Console.

However, when I begin to customize the form to fit my project-specific needs, I break the form, causing the form validation to fail. The error i get upon submitting the form is:

TypeError: Cannot read property 'length' of undefined at Object.convertString [as convert] (user.js:727) at user.js:145 at async.js:181 at iterate (async.js:262) at Object.async.forEachOfSeries.async.eachOfSeries (async.js:281) at Object.async.forEachSeries.async.eachSeries (async.js:214) at Object.self.convert (user.js:127) at convert (always.js:57) at async.js:718 at iterate (async.js:262)

My changes, other then adjusting the field definition object of my contact-form:index.js file, are mostly in the contact-form-widgets:widget.html file.

In the tutorial, the contact-form-widgets:widget.html view imports apostrophe-schemas:macros.html, and uses html files from the apostrophe-schemas and apostrophe-ui modules to build the html of the form. My specific questions therefore have to do with the importance of those two modules. Are those modules simply used for the front end display of the form? Do the contents of the views of those modules have any bearing on the submission and post-submissions tasks of the form? If the answer is negative, this means I am not configuring the form correctly, so therefore, are there any resources to help solve that problem?

Here is my contact-form:index.js config file:

var async = require('async');

module.exports = {
  extend: 'apostrophe-pieces',
  name: 'contact-form',
  label: 'Contact Form',
  alias: 'contactForm',
  addFields: [
    {
      name: 'name',
      type: 'string',
      label: 'First & Last Name',
      required: true
    },
    {
      name: 'company',
      type: 'string',
      label: 'Company Name',
      required: true
    },
    {
      name: 'email',
      type: 'string',
      label: 'Email Address',
      required: true
    },
    {
      name: 'phone',
      type: 'string',
      label: 'Phone Number & Extension',
      required: true
    },
    {
      name: 'subject',
      type: 'string',
      label: 'Subject',
      required: true
    },
    {
      name: 'message',
      type: 'string',
      label: 'Message',
      textarea: true,
      placeholder: "Don't be stupid"
    }
  ],
  permissionsFields: false,

  afterConstruct: function(self) {
    self.setSubmitSchema();
  },

  construct: function(self, options) {

    self.setSubmitSchema = function() {
      self.submitSchema = self.apos.schemas.subset(self.schema,
        [ 'name', 'company', 'email', 'phone', 'subject', 'message' ]
      );
    };

    self.submit = function(req, callback) {
      var piece = {};
      return async.series([
        convert,
        insert
      ], callback);
      function convert(callback) {
        return self.apos.schemas.convert(req, self.schema, 'form', req.body, piece, callback);
      }
      function insert(callback) {
        return self.insert(req, piece, { permissions: false }, callback);
      }
    };

  }
};
Jeff Wilkerson
  • 376
  • 2
  • 18
  • This is probably due to an error in the custom field configuration, so please share that code. It's certainly a fact that we need more nuanced and friendly error messages around that. – Tom Boutell Jan 17 '17 at 23:33
  • I added the custom field config. – Jeff Wilkerson Jan 18 '17 at 00:31
  • @boutell Any ideas? The error is coming from the apos-schema module, and is failing here: `if (field.required && !data[name].length)` inside a function called convertString. What string is being converted? I am naming all of my form fields properly, it seems. I am not understanding what data[name is suppose to be. – Jeff Wilkerson Jan 20 '17 at 00:52
  • Also, will the form submit if ANY button inside the form is clicked? It appears that is the behavior, and if so, that seems very obtrusive. I think its reasonable to have buttons inside a form tag that do not submit the form. How can I fix it so that the form only submits when clicking a submit button? – Jeff Wilkerson Jan 20 '17 at 00:56
  • Can you reproduce this in a fork of our sandbox project or another project that I can install? I'd be happy to take a look, I just don't see this problem in my environment so far. – Tom Boutell Jan 20 '17 at 22:21
  • As for the submit behavior you talked about, it's just example code in the tutorial, but the default type of a "button" element is "submit," so that's the behavior you get in any browser if you don't specify otherwise. It's nothing to do with Apostrophe. The JavaScript in our tutorial listens for a submit handler. You can change the behavior with click handlers and preventDefault() or a "type" other than "submit". I'll make type="submit" explicit though. – Tom Boutell Jan 21 '17 at 00:14
  • @boutell, thanks for your help. I've forked the project and submitted a pull request, although I am unable to start the sandbox project on my machine. If you can sift through what I pushed, I would be thrilled. In the mean time, i'll start from scratch with the form, and customize it one item at a time to see what the problem is. Thanks again! – Jeff Wilkerson Jan 21 '17 at 00:41
  • @boutell, thanks very much for the insight on the submit button. Been doing Front End Dev for 17 years and did not know that caveat! thats incredibly helpful! – Jeff Wilkerson Jan 21 '17 at 00:43

1 Answers1

0

I'm the lead developer of Apostrophe at P'unk Avenue. We had some conversation in another forum but just for the record, there turned out to be two issues:

  1. The form was submitting on any button click because that is what button elements do when they are of type "submit," and "submit" is the default value for type (at least in some browsers). It's not an Apostrophe issue and can be resolved by setting the type attribute as desired.

  2. The form markup was custom and did not have wrapper elements such as data-name="title", etc. (corresponding to the schema) around the actual form field elements. You may use custom markup but all of the "moving parts" found in our official schemaMacros.html need to be there, i.e. the data attributes need to exist.

We do plan to make it easier to use custom markup without those wrappers, at least in cases where we can figure out which fields are which without them.

FYI, an element of type="file" will not work out of the box, but check out the attachment field type in apostrophe's schemas, which is pretty amazing for that role.

Tom Boutell
  • 7,281
  • 1
  • 26
  • 23