4 Replies Latest reply on Nov 10, 2016 11:08 PM by Sanford Whiteman

    One ...form... to rule them all?

      I've been working on an experiment.  Over time, I've noticed many of our landing page forms varied between 4 to 7 specific fields, each varying on whether it was a required field.

       

      I decided to try making a landing page template where I could use just one form, and simply hide/unrequire fields if we didn't need them. I used several "mktoBoolean" metatags to toggle required status and field visibility. Then I applied Javascript for form verification, referencing a script I'd seen Sanford post in another thread. I tweaked here and there for my needs, and I'm almost there. But... still a few hurdles.

       

      Rather than including a long code block, here's the experiment: http://go.idt911.com/validation-test.html ...I can follow up with any bits requested.

       

      The challenges I've run into:

      1. How to toggle the whole verification on/off? This is so, when I have to use a unique form, I can ignore that validation if it can't encompass whatever is in the unique form. This way, I could still use the landing page template for those situations. I made a boolean metatag (jsvalidate) to toggle. Then I tried wrapping the script in something like "if (jsvalidate != false) { //validation code }, but it didn't work.

       

      2. Validating a Select field. Right now, I just have a regex to check if it's not empty, for proof-of-concept, but I believe there's a better way to validate select fields. The ways I tried, didn't work, though - they killed the script.

       

      3. Simplifying things? As it's an experiment, and I'm no JS expert, there seem to be spots that could be streamlined. An example is a group of if statements, to add a " noRequire" class. They're each a little different, but I assume maybe there's a way to simplify. Maybe some array. But, I thought I'd get outside input before muddling through. Also, Maybe there's some way to have a 'multiple choice' toggle that covers all fields, instead of one for each?

       

      4. Lastly... is this just a silly, insane idea? Are there reasons not to do it? I know it doesn't answer all scenarios - I'm just trying to prevent 100s of similar forms, if one will do. 

       

       

      included a screenshot of variables, for reference.

      togglers.jpg

        • Re: One ...form... to rule them all?
          Sanford Whiteman

          I certainly wouldn't say this is insane and indeed I encourage it -- as long there aren't so many fields that the variables pane must scroll endlessly!

           

          If you want a variable to disables all validation solely because the form might not include a fields for each corresponding Require* variable, that's unnecessary.  You can have the validation only apply to fields presently on the form. For example:

           

          var formEl = form.getFormElem()[0],
          allFields = [ 
          { 
            name : 'Company', 
            behaviors :  /* ... validators and other behaviors here */
          }, { 
            name : 'FirstNames', 
          
            behaviors :  /* ... validators and other behaviors here */
          }, 
          { 
            name : 'LastName', 
          
            behaviors :  /* ... validators and other behaviors here */
          } 
          ],
          fieldsPresent = fields.filter( function(itm){ 
            return !!formEl.querySelector('[name="' + itm.name + '"]'); 
          });
          
          // fieldsPresent now refers only to those fields that are present on the current form
          

           

           

          You won't be able to combine all of the booleans into a multiple choice variable (well, not without some very fancy stuff I won't get into here). So everything that's an independent on/off switch needs its own variable. This is unfortunate, since the Enable and Require variants for the same field should really be a slider or radio button set (Off/Enable/Require).

           

          If some fields will always be required if present (I would assume Email is one) then you can consolidate into one variable.

          • Re: One ...form... to rule them all?
            Sanford Whiteman

            (jsvalidate) to toggle. Then I tried wrapping the script in something like "if (jsvalidate != false) { //validation code }, but it didn't work.

            Variables are accessed using ${variablename}.

             

            Validating a Select field. Right now, I just have a regex to check if it's not empty, for proof-of-concept, but I believe there's a better way to validate select fields. The ways I tried, didn't work, though - they killed the script.

            I don't know why you'd need to validate anything other than non-empty, since the Select options are restricted at the form level and Marketo does the work of treating the first value ("Select...") as empty. If you want to restrict the values available to people, then you can remove certain options from the dropdown.

            • Re: One ...form... to rule them all?

              ok... so on the Select field, I can leave that as-is.

               

              On the ability to include forms that might have fields not being validated by the javascript...

               

              Looks like I'll have to hurt my brain learning how to rework the script. Just doing a quick glance... if I understand right, am I going in the right direction here? ( I suspect I'm not)

              ---------------------------------------------------------

              MktoForms2.whenReady(function(form) {

                   form.onValidate(function(builtInValid) {

                         if (!builtInValid) return;

                         form.submittable(true);

                         //Get values 

                         var vals = form.vals();

               

                         var emailRegExp =

                           /^[^\s@]+@([^\s@.,]+\.)+[^\s@.,]{2,}$/;

                         var phoneRegExp =

                           /^[\s()+-]*([0-9][\s()+-]*){6,20}(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i;

               

                       var validEmail = emailRegExp.test(vals.Email);

                       var validPhone = phoneRegExp.test(vals.Phone);

               

                        var formEl = form.getFormElem()[0], 

                       allFields = [  

                           {  

                             name : 'Email',  

                             behaviors :   if (!validEmail) {

                              // Prevent form submission 

                              form.submittable(false);

                              // Show error message, pointed at emailTest element 

                              var email = form.getFormElem().find("#Email");

                              form.showErrorMessage(

                                "Please enter valid email",

                                email);

                            } else {

                              form.submittable(form.submittable() != false);

                            }

                           }, {  

                             name : 'Phone',  

                             behaviors : 

                                 if (${fieldtelephonereq}) {

                                     if (!validPhone) {

                                       // Prevent form submission 

                                  form.submittable(false);

                                  // Show error message, pointed at phoneTest element 

                                  var phone = form.getFormElem().find("#Phone");

                                  form.showErrorMessage(

                                    "Please enter valid Phone",

                                    phone);

                                } else {

                                  form.submittable(form.submittable() != false);

                                }

                               }

                           }, {  

                        name : 'Industry',  

                        behaviors :  /* ... validators and other behaviors Copied here like above? */ 

                      }, {  

                        name : 'Title',  

                        behaviors :  /* ... validators and other behaviors here */ 

                      }, {  

                        name : 'Company',  

                        behaviors :  /* ... validators and other behaviors here */ 

                      }, {  

                        name : 'FirstNames',  

                        behaviors :  /* ... validators and other behaviors here */ 

                      },  {  

                        name : 'LastName',  

                        behaviors :  /* ... validators and other behaviors here */ 

                      }  

                  ], 

                    fieldsPresent = fields.filter( function(itm){  

                      return !!formEl.querySelector('[name="' + itm.name + '"]');  

                     }); 

               

                    form.onSubmit(function(form) {

                       alert("Success!"); // added for testing

                     });

               

              });

                • Re: One ...form... to rule them all?
                  Sanford Whiteman

                  Hmm... not really what I had in mind.

                   

                  The behavior array doesn't include any Forms API methods (submittable, showErrorMessage, etc.).  It contains merely conditions (regexes, comparison functions), predicates (whether comparisons are expected to be true or false), and error messages.

                   

                  You can pre-filter the behavior array so it only contains fields that are on the current form.

                   

                  And then you loop over the array, running each comparison/regex in turn and alerting on any errors.

                   

                  You can see some examples in my earlier posts (though I don't always express behaviors in such an organized way here because I want the code to be more concise -- at the expense of extensibility).