6 Replies Latest reply on Oct 10, 2013 9:48 AM by Aegis Kleais

    Trying to dynamically output form fields returns URL values

    k.randolph

      Hello,

       

      If there is a better way to go about this (which is quite likely), please let me know how to go about it.

       

      I'm working on some code that is supposed to dynamically set the form variables as regular variables so that we can be lazy and not have to refer to the variable with form.somevariable name.

       

      That part works perfectly.  Until I start testing for URL conflicts in which a URL variable has the same name.  For instance. . .

       

      I have a form that passes two variables; FirstName and LastName.  If I hit the page, the form shows up, I input a first and last name and click submit.  The code works perfectly.

       

      However, if I have URL variables with the same names, the code reports the url variable values instead of the form values.

      Some sample values;

      url.FirstName = Joe

      url.LastName = Black

      form.FirstName = Steve

      form.LastName = White

       

      My code that exposes the form variable will correctly find the form field names, but then when I 'evaluate' the value of the given form field, it will return the value of the URL variable of the same name rather than the form variable.

       

      What I am really wanting (as I described briefly up above) is to have code that automatically converts client, URL and Form variables into 'regular variables' so that you don't have to write lots of extra code grabbing them later on.  Frameworks like CFWHEELS and ColdBox do this by default, but at the company I work out, we aren't using any of them.  I need it to expose the URL variables, but give presidence to form variables if they have the same name, because they are likely to be intended to do an update or such.

       

      The code follows  Feel free to ignore the code for the URL and client variables if you wish as they don't directly affect how the form code works, I have tested with them commented out and I get the same result.  I provided all of it to give a more complete idea of what I have been toying with so far.  Please note that I don't normally use 'evaluate'.  There is probably a better way to go, but I don't know what it is.

       

      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

       

      <!--- Create a form so that we can post some form variables --->

      <form action="" method="post">

       

          First Name <input type="text" name="FirstName" />

          Last Name <input type="text" name="lastName" />

          <input type="submit" />

       

      </form>

       

      <!--- Set a variable to hold the list of URL variable names --->

      <cfset paramsurl = structKeyList(url)>

       

      <cfoutput>

      <br />

      URL variables:

       

      <!--- Loop through the list of url variables and then dynamically set a new variable to be equal to whatever is held by it --->

          <cfloop index="i" list="#paramsurl#">

              <cfset myDynVar = Evaluate(i)>

             

              <!--- Let's output the dynamically created variable as a test --->

              #i# = #myDynVar#<br />

          </cfloop>

      </cfoutput>

       

      <!--- If form fields exist --->

      <cfif isdefined("Form.FieldNames")>

          <cfoutput>

              <b>Field Names:</b> #Form.FieldNames#

              <p>

                  <b>Field Values:</b><br>

                  <cfloop INDEX="TheField" list="#Form.FieldNames#">

                      #TheField# = #Evaluate(TheField)#<br>

                      <cfset TheField = Evaluate(TheField)>

                  </cfloop>

              </p>

              Lets try and output the two form fields without using the "form." notation<br>

              FirstName : #FirstName# <br />

              LastName : #LastName#

          </cfoutput>

      </cfif>

      <br />

       

       

      The client variables currently available are:<br />

      <cfoutput>

          <cfset nVarCounter = 1>

          <cfloop list="#GetClientVariablesList()#" index="whichClientVar">

              #whichClientVar# : #client[whichClientVar]#<br />

              <cfset whichClientVar = Evaluate(whichClientVar)>

          </cfloop>

      </cfoutput>

        • 1. Re: Trying to dynamically output form fields returns URL values
          Aegis Kleais Level 3

          Though I highly don't recommend merging variable scopes into 1 melting pot, let me ask a couple questions first.

           

          1. You're posting data, so if you arrive at a page which HAS URL attributes you need to hold onto, you'll need to create a hidden form field and populate it with the CGI.query_string value.  Because if you arrive on test.cfm?this=that or even if your action attribute of your form points to "test.cfm?this=that" but the method is set to post, you're going to lose all your URL scope data when you submit the form.  To keep it, make a hidden field like I mentioned and if you populate it with the CGI.query_string value, you can process this on form submit.

           

          2. If you're throwing everything into the VARIABLES scope, but you want ot be made aware when 2 variables have the same name, you're basically just looking to see if any variable off the root of the CLIENT, FORM, and URL scopes has the same name as in another scope.  Right?  CLIENT.der would collide with URL.der, otherwise, when all is said and done, VARIABLES.der will have the value in it.

          • 2. Re: Trying to dynamically output form fields returns URL values
            k.randolph Level 1

            Hello,

             

            Thank you for replying.   For the purpose of this code, I do not need to worry about having a given variable persist between page postings.  The individual pages need to take care of that.

             

            This code is just to make basic coding easier and faster.  It should work much the same way that many of the Frameworks handle it.

             

            Form variables are greater than URL variables.  So if you have a form and URL variable and they both have the same name, then the form version of the variable should 'win'.  Hard coding the example might be something like this. . .

             

            <cfif isdefined("url.FirstName")>

                 <cfset FirstName = url.FirstName>

            </cfif>

            <cfif isdefined("form.FirstName")>
                 <cfset FirstName = form.FirstName>

            </cfif>

             

            In this example, if FirstName existed as both a url AND a form variable, it would be set to whatever the form value was since it was last.

             

            However, in the dynamic code that I was working on, if the variable exists as both a form and url version, my code will return the url version.  I do NOT want that to happen.

             

            I am guessing that there is a better/different way to go about this, but I'm not sure what it is.

            • 3. Re: Trying to dynamically output form fields returns URL values
              Aegis Kleais Level 3

              Try this:

               

              <cfset structAppend( FORM, {

                        'alpha' = 'bravo',

                        'charlie' = 'delta',

                        'echo' = 'foxtrot'

              }, true ) />

               

               

              <cfset structAppend( URL, {

                        'alpha' = 'zulu',

                        'lima' = 'mike',

                        'echo' = 'papa'

              }, true ) />

               

               

              <!--- List the scopes in ascending order of importance. --->

               

               

              <cfdump var="#FORM#" label="FORM scope" />

              <cfdump var="#URL#" label="URL scope" />

               

               

              <cfset scopes = "url,form">

               

               

              <cfloop list="#scopes#" index="i">

                        <cfloop list="#structKeyList( evaluate( i ) )#" index="j">

                                  <cfset structInsert( VARIABLES, j, evaluate( i & '["' & j & '"]' ), true ) />

                        </cfloop>

              </cfloop>

               

               

              <cfdump var="#VARIABLES#" abort="1" label="Combined Variables Scope" />

               

              What I did is insert 3 key/value pairs into the FORM and URL scope.  I then dumped the scopes to show their structure and values.  Then I defined a variable (scopes) which is a list of the least important scope to the most important.  After that, the loop I do simply goes through the SCOPES, their exisiting key/values and sets them into the VARIABLES scope.  Then, when it moves to the next scope of importance, it simply puts their value into the variables scope as well (overriding in the event it already exists), thus, the scopes defined later in the list override and replace.

               

              Then I just dump the VARIABLES scope (you'll notice it has the I, J and SCOPES variables in there that I used to create the loop.  If you perform this action in a function, simple make the I, J and SCOPES variables part of the LOCAL scope so they won't be in your VARIABLES scope.

              • 4. Re: Trying to dynamically output form fields returns URL values
                k.randolph Level 1

                Thanks!

                 

                I will test this and reply back.

                • 5. Re: Trying to dynamically output form fields returns URL values
                  k.randolph Level 1

                  Hello,

                   

                  I tested it and it appears to be working perfectly.  Can client variables be worked into it the same way?

                   

                  [edit]

                   

                  I added client to the list and it is working flawlessly!

                   

                  Thanks again!