We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 30223
    • 1,010 Posts
    The form doesn’t populate (show values) unless eForm can be made to think that it has been posted. This is because eForm is now super-cool in that it adds value="[+placeholder+]" to each form field (as well as selecting and checking the appropriate ones), but only AFTER the form has been posted. So even if you set the $fields or $_POST values in a function triggered by an event that happens before the form is parsed, these values are not inserted into the form.

    There’s nothing to stop you from adding these placeholders manually though. eForm will deal with them either way. Just have to remember that for radio buttons, check and select boxes you need to set [+fieldname:value+] placeholders.
      • 33372
      • 1,611 Posts
      Aha! That’s the trick then! I had tested using placeholders for other fields (and it did populate the field), but I forgot that there was a method for using placeholders with checkboxes, radio buttons, and select menus, and I didn’t know if my inserting them on my own would mess up eForm’s parsing routine. That would solve the whole issue! If the placeholders are in the form and I set their corresponding $fields values, then the form should populate. I’m going to test this later today on another similar situation, but I think that you just solved my problem. THANKS!
        "Things are not what they appear to be; nor are they otherwise." - Buddha

        "Well, gee, Buddha - that wasn't very helpful..." - ZAP

        Useful MODx links: documentation | wiki | forum guidelines | bugs & requests | info you should include with your post | commercial support options
        • 33372
        • 1,611 Posts
        Trying again to prepopulate an eForm, this time without modifying the core code at all. I’m using the example event function from the wiki to fake a POSTback, and that part seems to be working fine. However, I’m hung up on those pesky checkboxes, radio buttons, and select menus...

        I’ve added my own placeholder tags to my form chunk to all the regular text fields (e.g., value="[+street1+]"), and those are prepopulating fine. I can’t seem to get the [+fieldname:value+] placeholders to work for select menus, checkboxes, and radio buttons. Maybe someone here can help me figure out what I’m doing wrong.

        For example, in a select menu called "state" (whose field var has been preset to a saved value in the eFormOnBeforeFormParse event), I have all the US states as options with placeholders like this:

        <option value="AK" [+state:AK+]>AK</option>

        But that never returns a value, no matter what state is set to in the prepopulate function.

        I’m running eForm 1.4.4 on MODx 0.9.6. When I look through the eForm code, I see Djamoer’s additions there and they seem to indicate that I’m formatting my placeholders correctly and they should be replaced with selected="selected". What am I missing?

        Thanks in advance for your help!
          "Things are not what they appear to be; nor are they otherwise." - Buddha

          "Well, gee, Buddha - that wasn&#39;t very helpful..." - ZAP

          Useful MODx links: documentation | wiki | forum guidelines | bugs & requests | info you should include with your post | commercial support options
          • 30223
          • 1,010 Posts
          How do you fake the postback? I tried to find this in the wiki but didn’t see anything doing that. I can figure out how to do it but am curious on how you achieved it.

          The important part is that the form gets fully parsed so that the $formats array is populated. You can check that by adding this at (or about) line 571 in eform.inc.php and setting &debug=`1` (or 2 or 3).

          $debugText .= "<br /><strong>Formats array:</strong><pre>". var_export($formats,true).'</pre>';
          $debugText .= "<br /><strong>Fields array:</strong><pre>". var_export($fields,true).'</pre>';
          


          I had a go at this and the value got replaced correctly although at first I didn’t see the change. culprit: caching.

          There may be another pitfall if you have multiple="multiple" in your select statement (and a name like state[]) In that case the fields[’state’] will contain a numeric array of values and you woudl have to set it o something like $fields[’state’][0]="AK", $fields[’state’][1]="US"

            • 33372
            • 1,611 Posts
            Hey there -

            Thanks for helping me with this!

            The wiki article I was referring to is this one: http://wiki.modxcms.com/index.php/Populate_eform_with_dynamic_data

            I’m not doing it exactly like this, since I’m populating from SESSION vars and I don’t need access to the templates array. So my current function code is:
            function preFormParse(&$fields){
            
            /* Runs on eFormOnBeforeFormParse event 
             * Called just before the form is parsed; Parsing is done only if there is $_POST data valid to the form
             * Prepopulating code based on this example: http://wiki.modxcms.com/index.php/Populate_eform_with_dynamic_data */
            
               global $modx;
            
               $evt=&$modx->event; // reference to the snippet call event (not eFormOnBeforeFormParse event)
               $validFormId=($evt->params['formid']==$_POST['formid']); // replicate $isPostBack variable conditions
               $isPostBack=($validFormId && count($_POST)>0); // (bool) true if the form is being updated via POST
               
               if (!$isPostBack) { // Check for NOT postback, since we only want to prepopulate an empty form
                  if(!empty($_SESSION['order']['Name'])) $fields['Name']=$_SESSION['order']['Name'];
                  if(!empty($_SESSION['order']['lastName'])) $fields['lastName']=$_SESSION['order']['lastName'];
                  if(!empty($_SESSION['order']['company'])) $fields['company']=$_SESSION['order']['company'];
                  if(!empty($_SESSION['order']['street1'])) $fields['street1']=$_SESSION['order']['street1'];
                  if(!empty($_SESSION['order']['street2'])) $fields['street2']=$_SESSION['order']['street2'];
                  if(!empty($_SESSION['order']['city'])) $fields['city']=$_SESSION['order']['city'];
                  if(!empty($_SESSION['order']['state'])) $fields['state']=$_SESSION['order']['state'];
                  if(!empty($_SESSION['order']['zip'])) $fields['zip']=$_SESSION['order']['zip'];
                  if(!empty($_SESSION['order']['phone'])) $fields['phone']=$_SESSION['order']['phone'];
                  if(!empty($_SESSION['order']['email'])) $fields['email']=$_SESSION['order']['email'];
                  if(!empty($_SESSION['order']['s1_Name'])) $fields['s1_Name']=$_SESSION['order']['s1_Name'];
                  if(!empty($_SESSION['order']['s1_lastName'])) $fields['s1_lastName']=$_SESSION['order']['s1_lastName'];
                  if(!empty($_SESSION['order']['s1_company'])) $fields['s1_company']=$_SESSION['order']['s1_company'];
                  if(!empty($_SESSION['order']['s1_street1'])) $fields['s1_street1']=$_SESSION['order']['s1_street1'];
                  if(!empty($_SESSION['order']['s1_street2'])) $fields['s1_street2']=$_SESSION['order']['s1_street2'];
                  if(!empty($_SESSION['order']['s1_city'])) $fields['s1_city']=$_SESSION['order']['s1_city'];
                  if(!empty($_SESSION['order']['s1_state'])) $fields['s1_state']=$_SESSION['order']['s1_state'];
                  if(!empty($_SESSION['order']['s1_zip'])) $fields['s1_zip']=$_SESSION['order']['s1_zip'];
                  if(!empty($_SESSION['order']['s1_phone'])) $fields['s1_phone']=$_SESSION['order']['s1_phone'];
                  if(!empty($_SESSION['order']['couponCode'])) $fields['couponCode']=$_SESSION['order']['couponCode'];
                  if(!empty($_SESSION['order']['comments'])) $fields['comments']=$_SESSION['order']['comments'];
                  if(!empty($_SESSION['order']['list'])) $fields['list']=$_SESSION['order']['list'];
                  if(!$_SESSION['order']['list']) $fields['list']='Add to eNewsletter list'; // if this var has not been set, default to yes
                  if(!empty($_SESSION['order']['ship2Billing'])) $fields['ship2Billing']=$_SESSION['order']['ship2Billing'];
               }
               else { // the form has been posted, so pre-process any data here
                  $fields['ccNumber']=preg_replace("/\D/",'',$fields['ccNumber']); // remove any non-decimal characters
                  $fields['couponCode']=strtoupper(str_replace(' ','',$fields['couponCode'])); // remove all spaces and capitalize
               }
            
            return true;
            
            }


            This works for all the text input fields and textareas, but checkboxes and select menus (and I assume radio buttons, although my form has none of these) don’t get pre-populated.

            I guess that what I’m doing here is not actually faking a POSTback but just checking for its conditions. The last time I tried to cross this bridge, I modified the core code and then also had to unset the required and validation arrays and messages in my function when it was not a real POSTback. Now I’m starting to realize that doing it this way will also require some kludges, but hopefully not to the core code....

            It doesn’t look to me as if the $formats array should be populated using this method, since it’s not a real POSTback. Which makes me wonder where the placeholders are being set that are working (?). Perhaps the easiest method to make this work without modifying the core code would be to set [+fieldname:value+] placeholders for checkboxes, radio buttons, and select menus manually in the event function.

            Do you have another suggestion? I notice a lot of new tricks in the eForm code since I last went through it. I also haven’t tried using the $debug options to see exactly what happens yet.

            Just FYI: I converted all of the SHOPx checkout system to use eForm now. It works beautifully, and using the event functions I can save to the database, process the credit card and deal with the returned result, set placeholders for complex emails, etc. It’s currently set up to send data entered by the user to the server via AJAX, so the basket display updates shipping, tax, totals, etc. dynamically as you fill in the form. I still have a lot of work to do before it’s ready for public release, since I’ve been so swamped this summer that I’ve barely been able to keep my head above water. But eForm has been a really helpful tool in the process and made a lot of things much easier than they could’ve been otherwise.

            For example, combined with the code in the function above that strips out any non-decimal characters, a simple RANGE validation is enough to make sure that a credit card number is potentially valid:

            eform="Credit Card Number:string:1:Your Credit Card Number does not appear to be valid:#RANGE 300000000000000~399999999999999,4000000000000000~6999999999999999"

            There are regex’s out there to do this also, but this will catch a missing digit before it goes to the payment gateway.

            Thanks again for your help and for creating a great tool.


              "Things are not what they appear to be; nor are they otherwise." - Buddha

              "Well, gee, Buddha - that wasn&#39;t very helpful..." - ZAP

              Useful MODx links: documentation | wiki | forum guidelines | bugs & requests | info you should include with your post | commercial support options
              • 30223
              • 1,010 Posts
              You are indeed not faking a postback, although that is exactly what you need to do if you con;lt want to hack the core snippet. eFOrm only parses the form template if postback is true. (retrospectively I’m not so sure that was wise of me, although it saves a tiny amount of code running on first displaying the form it’s more hassle then it’s worth in cases like this smiley

              Why you are seeing simple singular values replaced and not the name:value variety is because simple values do not need any form processing. They relate directly to their respective place holders. To work out which values belong to which placeholders in the name:value variety however eForm needs to parse the form. This could probably be coded differently but were stuck with this for now.

              There are two options that I can see. Either you make a small change to the core or you replace the placeholders with your values directly in the event function.

              The change you need to make is simple. Move line 148 (or thereabouts) to above the $isPostback test:

              <?php	
              	//moved line 148 to here
              	$tpl = eFormParseTemplate($tpl,$isDebug);
              
              	if ($isPostBack) {
              
              		# parse form for formats and generate placeholders
              //removed following line
              //		$tpl = eFormParseTemplate($tpl,$isDebug);
              		foreach($formats as $k => $discard)
              			if(!isset($fields[$k])) $fields[$k] = ""; // store dummy value inside $fields
              
              	//skipped rest of code
              	}
              


              As far as I’m aware this is quite save and has no adverse effect to the rest of eForm. The second option you have alreay mentioned so I don;t need to elaborate on that.

              To finish a suggestion about validating credit cards. There are some excellent php classes that you could adapt and incorporate into a validation function. Here’s one but do a google search for "php mod 10 validation" and you’ll find many. http://www.sitepoint.com/article/card-validation-class-php

              To do a full verification you could use the class as is and write a simple function for eForm’s eFormOnValidate event. To do a simpler numbers only check you could extract the MOD 10 method and save is as a function. You could then set the eform attribute to

              eform="Credit Card Number:string:1:Your Credit Card Number does not appear to be valid:#FUNCTION validateCCNumber"


              Good luck
                • 33372
                • 1,611 Posts
                Making the change that you suggest to the core eForm code seems to do the trick. Maybe you should make that a parameter option in future versions ("Always parse form template/Parse only after POST", or something like that). I can see how it probably saves a little bit of execution time by not parsing the form when there’s no need, but for those of us who want to prepopulate it’d be nice to be able to use the code as distributed so it doesn’t break if updated.

                Setting placeholders from the function instead doesn’t work, however. I’m not sure why, but it seems like no placeholder that I set in this function is parsed into the form (even a simple "xyz" placeholder outside of the form fields). I’d try to figure out why, but your alternative solution works fine and I have plenty to do already.

                I’ve thought about integrating a "real" credit card verification class (or just a complex regex, of which there are many) into the checkout process, but so far I haven’t had the need. The actual number is being verified by Authorize.Net on submit anyway, so I just wanted to avoid things like missing digits and expiration dates in the past before sending it to them. It’s probably worth doing for the next generation, however, so thanks for the link.
                  "Things are not what they appear to be; nor are they otherwise." - Buddha

                  "Well, gee, Buddha - that wasn&#39;t very helpful..." - ZAP

                  Useful MODx links: documentation | wiki | forum guidelines | bugs & requests | info you should include with your post | commercial support options
                  • 28042 ☆ A M B ☆
                  • 24,524 Posts
                  Twelve years ago I coded a Perl script for "pre-validation" of credit cards; each card vendor has a certain format and certain number patterns. I forget exactly, but it was possible to determine if the number submitted was a possible valid Visa, Master Card, etc card by checking for these formats and patterns.
                    Studying MODX in the desert - http://sottwell.com
                    Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                    Join the Slack Community - http://modx.org
                    • 30223
                    • 1,010 Posts