Link to home
Start Free TrialLog in
Avatar of jturkington
jturkington

asked on

Reusing a Form For Insert & Updates

Trying to figure out how to get the following code to work properly. The code relies on a URL.jobid to determine if its in edit or insert mode. The problem i am having is in edit mode when a validation error occurs, all the form.variables are overwritten with the database values instead of the form field keeping the users last input. Add mode works fine. Any help on how to improve this would be much appreciated !!

The Code: -

<cfparam name="FORM.contact" default="">
<cfparam name="FORM.job" default="">
<cfparam name="URL.Msg" default="">
<cfset VARIABLES.Msg="#URL.Msg#">

<!--- check if the form is submitted with no error messages--->
<cfif isDefined( "form.btnSubmit" ) and VARIABLES.Msg is "" >

   <!--- Validate --->

   <!--- If there are no errors --->
   <cfif VARIABLES.Msg is "">
      <cfif isDefined( "URL.jobid" ) >
      Do update
      <cfelse>
                Do Insert
      </cfif>
   <cfelse>
      <!-- validation failed, make the message pretty for the user -->
      <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
   </cfif>
</cfif>

<!--- Check if in edit mode - when URL.JobID is present it means we are in edit mode --->
<cfif isDefined( "URL.jobid" ) >
   <!--- get the data from the db so we can populate the form --->
      <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
         <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
         <cfprocresult name="Get_Job_Details">
      </cfstoredproc>
   <!--- Set job details as valuye for FORM variables --->
   <cfset FORM.contact = "#Get_JobDetails.contact#">
   <cfset FORM.job = "#Get_JobDetails.job#">
   <CFSET FormTitle = "Update Job">
   <CFSET ButtonText = "Update">
      
<cfelse>
   <CFSET FormTitle = "Insert Job">
   <CFSET ButtonText = "Insert">
</cfif>

<cfif VARIABLES.Msg is not "">
    <p>#VARIABLES.Msg#</p>
</cfif>

<form name="dsp_job_addedit" method="post" action="dsp_Job_addedit.cfm<cfif cgi.query_string NEQ "">?#cgi.query_string#</cfif>">

#VARIABLES.formtitle#<br />

<input id="contact_name"  name="contact_name"  value="#FORM.contact_name#" type="text" />

<input id="job"  name="job"  value="#FORM.job#" type="text" />

<input type="submit" name="btnSubmit" value="<cfoutput>#buttontext#</cfoutput>" class="button" />

</form>

Cheers

JT
Avatar of James Rodgers
James Rodgers
Flag of Canada image

try changing this

<cfif isDefined( "URL.jobid" ) >

to this

<cfif isDefined( "URL.jobid" )  and not isDefined("btnSubmit")>
also try adding cliernt side validation

<script language="JavaScript" type="text/javascript">
function validateForm(objForm){

      strErr='';
      objFocus=''
      if(!objForm.contact_name.value.replace(/^\s+|\s+$/g,"").length){
            if(!strErr){
                  objFocus=objForm.contact_name;
            }
            strErr+='field 1 is empty\n'
      }
      
      if(!objForm.job.value.replace(/^\s+|\s+$/g,"").length){
            if(!strErr){
                  objFocus=objForm.job;
            }
            strErr+='field 2 is empty\n'
      }
      
      if(strErr){
            alert(strErr);
            objFocus.focus();
      }
return !strErr;
}

</script>

called in teh form tag as ... onSubmit="return validaetForm(this)" ...
Avatar of rob_lorentz
rob_lorentz


only use url.jobId the first time into the page. if defined, get record, fill form fields and create a form field for jobId. Then in the action look to see if form.jobId has a value, yes=update, no=insert.

here is the code.


<cfparam name="form.JobId" default="0">

<cfparam name="FORM.contact" default="">
<cfparam name="FORM.job" default="">
<cfparam name="URL.Msg" default="">
<cfset VARIABLES.Msg="#URL.Msg#">

<!--- check if the form is submitted with no error messages--->
<cfif isDefined( "form.btnSubmit" ) and VARIABLES.Msg is "" >

   <!--- Validate --->

   <!--- If there are no errors --->
   <cfif VARIABLES.Msg is "">
      <cfif form.jobId >
           Do update
      <cfelse>
         Do Insert
      </cfif>
   <cfelse>
      <!-- validation failed, make the message pretty for the user -->
      <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
   </cfif>
</cfif>

<!--- Check if in edit mode - when URL.JobID is present it means we are in edit mode --->
<cfif isDefined( "URL.jobid" ) and not Form.JobId>
   <!--- get the data from the db so we can populate the form --->
     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
        <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
        <cfprocresult name="Get_Job_Details">
     </cfstoredproc>
   <!--- Set job details as valuye for FORM variables --->
   <cfset FORM.contact = "#Get_JobDetails.contact#">
   <cfset FORM.job = "#Get_JobDetails.job#">
   <CFSET FormTitle = "Update Job">
   <CFSET ButtonText = "Update">
   <cfset form.jobId = url.jobId>
<cfelse>
   <CFSET FormTitle = "Insert Job">
   <CFSET ButtonText = "Insert">
</cfif>

<cfif VARIABLES.Msg is not "">
    <p>#VARIABLES.Msg#</p>
</cfif>

<form name="dsp_job_addedit" method="post" action="dsp_Job_addedit.cfm">

#VARIABLES.formtitle#<br />

<input id="jobId" name="jobId" value="#form.jobId#" type="Hidden">
<input id="contact_name"  name="contact_name"  value="#FORM.contact_name#" type="text" />

<input id="job"  name="job"  value="#FORM.job#" type="text" />

<input type="submit" name="btnSubmit" value="<cfoutput>#buttontext#</cfoutput>" class="button" />

</form>

sorry missed the submit button and title. try this...


<cfparam name="form.JobId" default="0">

<cfparam name="FORM.contact" default="">
<cfparam name="FORM.job" default="">
<cfparam name="URL.Msg" default="">
<cfset VARIABLES.Msg="#URL.Msg#">

<!--- check if the form is submitted with no error messages--->
<cfif isDefined( "form.btnSubmit" ) and VARIABLES.Msg is "" >

   <!--- Validate --->

   <!--- If there are no errors --->
   <cfif VARIABLES.Msg is "">
      <cfif form.jobId >
           Do update
      <cfelse>
         Do Insert
      </cfif>
   <cfelse>
      <!-- validation failed, make the message pretty for the user -->
      <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
   </cfif>
</cfif>

<!--- Check if in edit mode - when URL.JobID is present it means we are in edit mode --->
<cfif isDefined( "URL.jobid" ) and not Form.JobId>
   <!--- get the data from the db so we can populate the form --->
     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
        <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
        <cfprocresult name="Get_Job_Details">
     </cfstoredproc>
   <!--- Set job details as valuye for FORM variables --->
   <cfset FORM.contact = "#Get_JobDetails.contact#">
   <cfset FORM.job = "#Get_JobDetails.job#">
   <cfset form.jobId = url.jobId>
</cfif>

<cfif form.jobId>
   <CFSET FormTitle = "Update Job">
   <CFSET ButtonText = "Update">
<cfelse>
   <CFSET FormTitle = "Insert Job">
   <CFSET ButtonText = "Insert">
</cfif>

<cfif VARIABLES.Msg is not "">
    <p>#VARIABLES.Msg#</p>
</cfif>

<form name="dsp_job_addedit" method="post" action="dsp_Job_addedit.cfm">

#VARIABLES.formtitle#<br />

<input id="jobId" name="jobId" value="#form.jobId#" type="Hidden">
<input id="contact_name"  name="contact_name"  value="#FORM.contact_name#" type="text" />

<input id="job"  name="job"  value="#FORM.job#" type="text" />

<input type="submit" name="btnSubmit" value="<cfoutput>#buttontext#</cfoutput>" class="button" />

</form>
Avatar of jturkington

ASKER

Cheers guys, is my framework getting messy is their better way of handling dual purpose forms ?

Any other framework examples would be much appreciated if you think necessary

Will give your example a go in the meantime rob_lorentz

Cheers

JT
Okay the way I do it is as follows: (generalized example)

<cfset errorflag = false>
<cfset editflag = IsDefined("URL.ID")>


<cfif IsDefined("form.submitbutton")>

check for errors.  If an error found set errorflag to true else do insert or update and cflocation to menu or whereever

<cfelseif editflag>

<cfquery datasource="mydsn" name="GetData">
SELECT col1, col2, etc FROM mytable WHERE id=#URL.id#
</cfquery>

</cfif>


<form ...etc >

<cfoutput>

<input type="text" name="field1" value="<cfif errorflag>#Form.field1#<cfelse><cfif editflag>#GetData.col1#</cfif></cfif>">
etc...

</cfoutput>

</form>
>>>Any help on how to improve this would be much appreciated !!
i do not rely or urls if its edit or not.

I suggest using form variables instead.

sumthing like  <cfif isDefined( "FORM.jobid" ) and FORM.jobid neq "">..

just to avoid user inputted urls..

user could just type in the URL.jobid in the url.
(unlikely? -- well just dont trust the user. change it to form submit instead of checking the url.)
mrichmon tried implementing your example but got myself a little confused. Where do i set the variables for Add and Edit exactly ? do i use cfset or cfparam, add and edit are not working to plan  HELP ?

Code so far:  -

<cfset errorflag = false>
<cfset editflag = IsDefined("URL.jobid")>

<!--- Set Variables For Add ? --->
<cfparam name="FORM.job_title" default="">
<cfparam name="URL.Msg" default="">
<cfset VARIABLES.Msg="#URL.Msg#">
<cfset FormTitle = "Add Job">
<cfset ButtonText = "Add Job">

<cfif IsDefined("FORM.submitbutton")>

      <cfif not len(FORM.job_title)>
            <cfset VARIABLES.Msg=VARIABLES.Msg & "<li>You must enter a Job Title</li>">
            <cfset errorflag = true>
      </cfif>
            
      <cfif VARIABLES.Msg is "">
            
            <!--- Perform Update Or Add --->
            <cfif errorflag IS false>
                  Do update
            <cfelse>
                  <!--- Add Job into the Jobs Table --->
                  <cfinclude template="/Jobs/Add/qry_Add_Job.cfm">
            
                  <!--- Remember the status code returned by the qry_Add_Job stored procedure --->
                  <CFSET InsertStatus = CFSTOREDPROC.StatusCode>
            
                  <!--- Display message based on status code reported by stored procedure --->
                  <cfswitch EXPRESSION="#InsertStatus#">
                        <!--- If the stored procedure returned a "success" status --->
                        <cfcase value="1">
                              <!--- If The Insert Was Successful Go To Next Page --->
                              <cflocation url="next_page.cfm?jobid=#jobid#" addtoken="no">
                        </cfcase>
                        <cfdefaultcase>
                              <cfset VARIABLES.Msg="<h3>ENTRY ERROR</h3>The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
                              <cfset VARIABLES.Msg=VARIABLES.Msg & "<li><b style='color:red'>The procedure returned an unknown status code. Please Contact Support</b></li>">
                              <cfset errorflag = true>
                        </cfdefaultcase>
                  </cfswitch>
            </cfif>
            
      <cfelse>
            <!-- validation failed, make the message pretty for the user -->
            <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
      </cfif>

<cfelseif editflag>

      <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
                      <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
            <cfprocresult name="Get_JobDetails">
      </cfstoredproc>
      
                <!--- Set Variables For Edit ? --->
                <cfset FORM.job_title = "#Get_JobDetails.job_title#">
      <cfset FormTitle = "Edit Job">
      <cfset ButtonText = "Edit Job">

</cfif>

<cfoutput>
  <cfif VARIABLES.Msg is not "">
    <p>#VARIABLES.Msg#</p>
  </cfif>
</cfoutput>

<form name="formreuse" method="post" action="formreuse.cfm<cfif cgi.query_string NEQ "">?<cfoutput>#cgi.query_string#</cfoutput></cfif>">

<cfoutput>
#VARIABLES.FormTitle#<br /><br />

<input type="text" name="job_title" value="<cfif errorflag>#Form.Job_title#<cfelse><cfif editflag>#Get_JobDetails.job_title#</cfif></cfif>"><br /><br />

<input type="submit" name="submitbutton" value="<cfoutput>#buttontext#</cfoutput>" class="button" />

</cfoutput>

</form>

Cheers

JT


in my example the form.jobId is the flag to either insert or update. if it has a value then update else insert.

<!--- did we get passed a job id AND did we read it yet? --->
<cfif isDefined( "URL.jobid" ) and not Form.JobId>
   <!--- get the data from the db so we can populate the form --->
     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
        <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
        <cfprocresult name="Get_Job_Details">
     </cfstoredproc>
   <!--- Set job details as valuye for FORM variables --->
   <cfset FORM.contact = "#Get_JobDetails.contact#">
   <cfset FORM.job = "#Get_JobDetails.job#">
   <cfset form.jobId = url.jobId>    <!--- save the jobId to signal update when the user posts form --->
</cfif>

<!--- did we get a record from the db?  --->
<cfif form.jobId>
   <!--- yes, this is an update --->
   <CFSET FormTitle = "Update Job">
   <CFSET ButtonText = "Update">
<cfelse>
   <!--- otherwise its an insert --->
   <CFSET FormTitle = "Insert Job">
   <CFSET ButtonText = "Insert">
</cfif>


then when you post the form back to yourself you will have form.jobId so you can check it when you go to insert or update.
<cfset errorflag = false>
<cfset editflag = IsDefined("URL.jobid")>

<!--- took out a lot of stuff from here.....
<cfset VARIABLES.Msg="">

<cfif IsDefined("FORM.submitbutton")>

     <cfif not len(FORM.job_title)>
          <cfset VARIABLES.Msg=VARIABLES.Msg & "<li>You must enter a Job Title</li>">
          <cfset errorflag = true>
     </cfif>
         
     <cfif NOT errorFlag><!--- since you have an errorflag use it here too - faster than a test on a string
         
          <!--- Perform Update Or Add --->
          <cfif editflag>
               Do Update
          <cfelse>
               <!--- Add Job into the Jobs Table --->
               <cfinclude template="/Jobs/Add/qry_Add_Job.cfm">
         
               <!--- Remember the status code returned by the qry_Add_Job stored procedure --->
               <CFSET InsertStatus = CFSTOREDPROC.StatusCode>
         
               <!--- Display message based on status code reported by stored procedure --->
               <cfswitch EXPRESSION="#InsertStatus#">
                    <!--- If the stored procedure returned a "success" status --->
                    <cfcase value="1">
                         <!--- If The Insert Was Successful Go To Next Page --->
                         <cflocation url="next_page.cfm?jobid=#jobid#" addtoken="no">
                    </cfcase>
                    <cfdefaultcase>
                         <cfset VARIABLES.Msg="<h3>ENTRY ERROR</h3>The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
                         <cfset VARIABLES.Msg=VARIABLES.Msg & "<li><b style='color:red'>The procedure returned an unknown status code. Please Contact Support</b></li>">
                         <cfset errorflag = true>
                    </cfdefaultcase>
               </cfswitch>
          </cfif>
         
     <cfelse>
          <!-- validation failed, make the message pretty for the user -->
          <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
     </cfif>

<cfelseif editflag>

     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
                      <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
           <cfprocresult name="Get_JobDetails">
     </cfstoredproc>
</cfif>

<cfoutput>
  <cfif errorflag>
    <p>#VARIABLES.Msg#</p>
  </cfif>
</cfoutput>

<form name="formreuse" method="post" action="formreuse.cfm<cfif cgi.query_string NEQ "">?<cfoutput>#cgi.query_string#</cfoutput></cfif>">

<cfoutput>
<cfif Editflag>Edit Form<cfelse>Add Form</cfif><br /><br />

<input type="text" name="job_title" value="<cfif errorflag>#Form.Job_title#<cfelse><cfif editflag>#Get_JobDetails.job_title#</cfif></cfif>"><br /><br />

<input type="submit" name="submitbutton" value="<cfif editflag>Edit<cfelse>Add</cfif>" class="button" />

</cfoutput>

</form>
Thanks mrichmon crashes out when submitting in edit mode instead of displaying "DO UPDATE" at the top of the page ?
Sorry about last comment !!

I meant

Thankyou for the code mrichmon

but the problem i am having is as above
Crashess?  with what error?
HTTP 500 Internal Server Error

Took out my add code to see if it would make a difference, but no go........

Error occurs when submitting in edit mode, add works though ?


<cfset errorflag = false>
<cfset editflag = IsDefined("URL.jobid")>

<!--- took out a lot of stuff from here..... --->
<cfset VARIABLES.Msg="">

<cfif IsDefined("FORM.submitbutton")>

     <cfif not len(FORM.job_title)>
          <cfset VARIABLES.Msg=VARIABLES.Msg & "<li>You must enter a Job Title</li>">
          <cfset errorflag = true>
     </cfif>
         
     <cfif NOT errorFlag><!--- since you have an errorflag use it here too - faster than a test on a string --->
         
          <!--- Perform Update Or Add --->
          <cfif editflag>
               Do Update
          <cfelse>
               Do Add
          </cfif>
         
     <cfelse>
          <!-- validation failed, make the message pretty for the user -->
          <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
     </cfif>

<cfelseif editflag>

     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
                    <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
                            <cfprocresult name="Get_Settings" resultset="1">
                              <cfprocresult name="Get_JobDetails" resultset="2">
     </cfstoredproc>
</cfif>

<cfoutput>
  <cfif errorflag>
    <p>#VARIABLES.Msg#</p>
  </cfif>
</cfoutput>

<form name="formreuse" method="post" action="formreuse.cfm<cfif cgi.query_string NEQ "">?<cfoutput>#cgi.query_string#</cfoutput></cfif>">

<cfoutput>
<cfif Editflag>Edit Form<cfelse>Add Form</cfif><br /><br />

<input type="text" name="job_title" value="<cfif errorflag>#Form.Job_title#<cfelse><cfif editflag>#Get_JobDetails.job_title#</cfif></cfif>"><br /><br />

<input type="submit" name="submitbutton" value="<cfif editflag>Edit<cfelse>Add</cfif>" class="button" />

</cfoutput>

</form>
check the url that is in the action of the form when doing an edit....
Try this:

put <cfabort> right after the "Do Update" and see if it still crashes
nope it doesnt, thats where the cflocation comes in.......  sorry i should have thought of that mrichmon

one more question mrichmon.......

I have a situation where i want to a use a records details to create a new record, is it possible to tweak the framework above to do this ??

FORM Framework should be able to
Add a record
Edit the record
Use Edit record details to create a new record from it ??

Thanks for all your help to date !!

JT
Sort of like a template?

I would send in template=ID in the URL instead of jobID=id

Then add logic to the page to treate template ID as an add, but to fill in the defaults.
yes like a template.....

how would we go about achieving this with your framework above ??
Basically same as an edit, but the URL variable would be templateID instead of JobID

Here is some code:

<cfset errorflag = false>
<cfset templateflag = IsDefined("URL.templateID")><!--- change here --->
<cfset editflag = IsDefined("URL.jobid")>

<!--- took out a lot of stuff from here..... --->
<cfset VARIABLES.Msg="">

<cfif IsDefined("FORM.submitbutton")>

     <cfif not len(FORM.job_title)>
          <cfset VARIABLES.Msg=VARIABLES.Msg & "<li>You must enter a Job Title</li>">
          <cfset errorflag = true>
     </cfif>
         
     <cfif NOT errorFlag><!--- since you have an errorflag use it here too - faster than a test on a string --->
         
          <!--- Perform Update Or Add --->
          <cfif editflag>
               Do Update
          <cfelse>
               Do Add
          </cfif>
         
     <cfelse>
          <!-- validation failed, make the message pretty for the user -->
          <cfset VARIABLES.Msg="The following error(s) were detected:<ul>#VARIABLES.Msg#</ul>">
     </cfif>

<cfelseif editflag OR templateflag><!--- change here --->

     <cfstoredproc procedure="spSelect_JobDetails" datasource="#request.dsn#">
                    <cfprocparam type="In" maxlength="6" cfsqltype="cf_sql_integer" value="#VAL(URL.jobid)#" null="no">
                         <cfprocresult name="Get_Settings" resultset="1">
                         <cfprocresult name="Get_JobDetails" resultset="2">
     </cfstoredproc>
</cfif>

<cfoutput>
  <cfif errorflag>
    <p>#VARIABLES.Msg#</p>
  </cfif>
</cfoutput>

<form name="formreuse" method="post" action="formreuse.cfm<cfif cgi.query_string NEQ "">?<cfoutput>#cgi.query_string#</cfoutput></cfif>">

<cfoutput>
<cfif Editflag>Edit Form<cfelse>Add Form</cfif><br /><br />

<input type="text" name="job_title" value="<cfif errorflag>#Form.Job_title#<cfelse><cfif editflag OR templateflag>#Get_JobDetails.job_title#</cfif></cfif>"><br /><br /><!--- change here --->

<input type="submit" name="submitbutton" value="<cfif editflag>Edit<cfelse>Add</cfif>" class="button" />

</cfoutput>

</form>

I made 3 changes indicated by <!--- change here --->
Thanks again mrichmon, I have a habit of giving every form element a: - <cfparam name="FORM.name" default=""> i take it this is not necessary unless i am giving it a default other than "" 

If i need to add in defaults for an add page eg.. drop down boxes from database values , default text for textareas etc..
i would perform this under: - ?

<!--- took out a lot of stuff from here..... --->
<cfset VARIABLES.Msg="">

<!--- Get Database Values To populate the Form Field Values --->
<cfinclude template="qry_select_formreuse_defaults.cfm">
<cfparam name="FORM.jobtitle" default="#Get_Defaults.job_title#"

Cheers

JT
Another question is there any nice tricks to make this page read only, ie.. just a display page then they click on a update / template to make it editable, addable etc..

Or should i have a separate page for displaying the job etc.. with the appropriate buttons

Just want to cut down on hassle of keeping the display page & edit/add/template page in synch as there will be constant changes to the form..

Cheers

JT
Hello mrichmon when you get the time can you let me know your advice on my above posts

Best regards

JT
ASKER CERTIFIED SOLUTION
Avatar of mrichmon
mrichmon

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for the input mrichmon, i will try this out ...

Hope you had a nice weekend !

Best regards

JT