I have a small form that loops from 1 to 30 and assigns variables. After these variables are saved to the database, I am having some trouble figuring out how to set the value of the input as the value from the database. Here is a some of my code.
<cfloop index="i"
from="1"
to="30">
<select name="supply_#i#"
id="supply_#i#"
/>
<cfloop query="GetDescriptor">
<option value="#GetDescriptor.Code#">
#GetDescriptor.Descriptor#
</option>
</cfloop>
</select>
<input type="text"
name="quant_#i#"
id="quant_#i#"
/>
</cfloop>
Once complete, the user saves all 30 values to the database. When they attempt to view or edit the form, I need to show the previously selected value. I really don't know how to "nest" coldfusion variables together, or if it is even possible, but here is an example of the VIEW/EDIT .cfm that does not work, but shows you what I am trying to accomplish with the values.
<cfloop index="i"
from="1"
to="30">
<cfset "supply_#i#" = #QUERY.supply#i##>
<cfset "quant_#i#" = #QUERY.quant#i##>
<select name="supply_#i#"
id="supply_#i#"
/>
<cfloop query="GetDescriptor">
<option value="#GetDescriptor.Code#"
<cfif #VARIABLES.supply_#i## EQ '#GetDescriptor.Code#'>
SELECTED="SELECTED"
</cfif> >
#GetDescriptor.Descriptor#
</option>
</cfloop>
</select>
<input type="text"
name="quant_#i#"
id="quant_#i#"
value ="#VARIABLES.quant_#i##"
/>
</cfloop>
I think the easiest way to accomplish this is to use array notation. That is, use brackets instead of dots. Since all variables scopes are structs you can do this.
variables["foo"]
is equivalent to
variables.foo
So in your case, you probably want to reference
#VARIABLES["supply_#i#"]#
or, perhaps
#VARIABLES["supply_" & i]#
(Too long for comments)
What is the actual structure of the db table the values are inserted into? The variable names suggest you are using a denormalized db design. If so, consider normalizing the structure and storing the data in rows (SupplyCode, Quantity), rather than columns (Supply1,Qty1,Supply2,Qty2,....). The normalized structure is a lot easier to query, and supports as many or as few entries as needed.
Simply query the table and use a query loop to display the existing values. Use currentRow in place of the index variable i:
<cfquery name="existingEntries" ...>
SELECT SupplyCode, Quantity
FROM YourTable
ORDER BY .....
</cfquery>
<cfloop query="existingEntries">
<select name="SupplyCode_#currentRow#" id="SupplyCode_#currentRow#">
<cfloop query="GetDescriptor">
<option value="#GetDescriptor.Code#"
<cfif existingEntries.SupplyCode EQ GetDescriptor.Code>
SELECTED="SELECTED"
</cfif>>
#GetDescriptor.Descriptor#
</option>
</cfloop>
</select>
<input type="text" name="Quantity_#currentRow#" value ="#existingEntries.Quantity#" .... />
</cfloop>
NB: Typically you would store a FK ID from the GetDescriptor table, ie "SupplyID" rather than a string code or description, ie "SupplyCode"
Related
I have made a dynamic form that combines a list of individuals. In this list, I have a field that contains the values of a dynamic list. My concern is that this field (#id_p#_state) is multiplied by the initial query and I want to avoid that. the result I have is for example if I have 10 results in the first query, each line of the second is x10
<cfinvoke component="cfc_query" method="methode_h" returnvariable="result">
<cfinvokeargument name="id_atser" value="#id#">
</cfinvoke>
<cfinvoke component="cfc_query" method="methode_state" returnvariable="result_state">
</cfinvoke>
<cfoutput query="result">
<tr>
<td>#lastname# #firstname# #id_personne#</td>
<cfloop from="1" to="#daysInMonth(createdate(datepart('yyyy',now()),form.date_periode,1))#" index="boucle">
<td><cfinput name="#id_personne#_date_presence" type="text" value="#dateformat(createdate(datepart('yyyy',now()),form.date_periode,boucle),'dd/mm/yyyy')#" size="7"></td>
<td>
<cfselect name="#id_p#_state" style="width: 32px;">
<cfloop query="result_state">
<cfoutput>
<option value="#id_state#">#description#</option>
</cfoutput>
</cfloop>
</cfselect>
</td>
</cfloop>
</tr>
</cfoutput>
You have a CFOUTPUT nested inside of a CFOUTPUT loop.
Get rid of the redundant CFOUTPUT around your option tag and this should clean up your output.
For the life of me I can't get CFIF to give me a true result when using the EQ operator with 2 equal fields . Below is the CF code:
<select class="form-control" name="sales_contact_id">
<cfoutput query="rc.getPartnerContacts">
<cfif rc.getPartnerContacts.id EQ rc.getPartner.sales_contact_id>
<cfoutput><option value="#rc.getPartnerContacts.id#" selected="selected">#fname# #lname#</option>
</cfoutput>
<cfelse>
<cfoutput><option value="#rc.getPartnerContacts.id#">#fname# #lname# #rc.getPartner.sales_contact_id#</option>
</cfoutput>
</cfif>
</cfoutput>
</select>
I put the #rc.getPartner.sales_contact_id# into the option text to show the value of the variable.
And this is the HTML output:
<select name="sales_contact_id" class="form-control">
<option value="1">David Elliott 2</option>
<option value="2">James Knight 2</option>
<option value="3">Fred Bloggs 2</option>
<option value="4">John Doe 2</option>
<option value="5">Jane Smith 2</option>
</select>
The value of the rc.getPartner.sales_contact_id field is 2 which the same as the id field for the 'James Knight' record in the rc.getPartnerContacts recordset. The CFIF statement should be true for the James Knight record so that this option is the default within the drop down list. I've tried using val(), I've tried subtracting one from the other and then using a CFIF EQ 0 and still won't work!
I'm sure that this is a really simple mistake but I can't see it!!!
This is a formatted comment. When in doubt, look at your data.
<cfdump var="#rc.getPartnerContacts#">
<cfoutput query="rc.getPartnerContacts">
<cfif rc.getPartnerContacts.id EQ rc.getPartner.sales_contact_id>
yes
<cfelse>
no ID is #id# and sales contact id is #rc.getPartner.sales_contact_id#
</cfif>
<br>
A facepalm moment - The <cfoutput> within a <cfoutput> caused the problem.
I'm working on code where I am getting two lists. I'm trying to use those lists to pre-select items in select box having the "multiple" attribute. However, I am unable to maintain the selections.
Code:
<select name="sbbox" id="sbbox" class="can" multiple>
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(k,getproducts.ptype)#>selected</cfif>>#k#</option>
</cfloop>
</select>
Sample values:
lstFinds = abc,xyz
getproducts.ptype also contains values like abc,xyz
I want to keep both selected, if both values exists for the user. If one exists, keep one selected. If none are selected, keep none.
I also tried using listContains, but it did not work.
Transferred from pastebin linkL
The ptype values are coming as comma separated in the database ie "abc,wed,mon,def". Whatever those values are, I need to match and selected the ones which have the same value in the listFind. I hope I made it clearer.
<cfset lstFinds = 'abc,xyz,def,www,kkr,mon,tue,wed'>
<cfquery name="getproducts" datasource="cdfg">
select ptype
from
mytable
where
ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#id#">
</cfquery>
<select name="sbbox" id="sbbox" class="can" multiple>
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(k,getproducts.ptype)#>selected</cfif>>#k#</option>
</cfloop>
</select>
There are three things wrong with this:
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(k,getproducts.ptype)#>selected</cfif>>#k#</option>
</cfloop>
First, as others have mentioned, in the listfindnocase function, the list comes first.
Next, the reason you are not getting the desired results after sorting out the first problem, is that getproducts.ptype is not a list. It is the value from the first row of the query. To get all the values in a list, use the valuelist() function.
Finally, the correct syntax for having an option selected is selected="selected". So the code block above should be this:
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#"
<cfif listfindnocase(ValueList(getproducts.ptype), k)>
selected="selected"
</cfif>>#k#
</option>
</cfloop>
Ok, the asker provided the following code via a Pastebin
<cfset lstFinds = 'abc,xyz,def,www,kkr,mon,tue,wed'>
<cfquery name="getproducts" datasource="cdfg">
select ptype
from
mytable
where
ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#id#">
</cfquery>
these are coming from database column ptype of a table as: abc,wed,mon,def
<select name="sbbox" id="sbbox" class="can" multiple>
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(k,getproducts.ptype)#>selected</cfif>>#k#</option>
</cfloop>
</select>
I ran the following code as at cflive.net
<cfset lstFinds = 'abc,xyz,def,www,kkr,mon,tue,wed'>
<cfset getProducts = {pType = "abc,wed,mon,def"}>
<cfoutput><select name="sbbox" id="sbbox" class="can" multiple>
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(getproducts.ptype,k)#>selected</cfif>>#k#</option>
</cfloop>
</select></cfoutput>
When I run this code, abc, def, mon, and wed are selected. Should these not be selected, or should others be checked?
This code appears to be doing what you are asking. The only changes I made
Changed the logic as per what Matt suggested in question comments.
Because I don't have the data to run a query against, I setup a getProducts structure with the key "pType" and the values as Asker suggested they might be. For the purpose here, my sample struct is functionally identical to a one-row query.
Finally, is it possible that you're trying to pull this from multiple rows? You might try
<cfset variables.ptypes = valuelist(getproducts.ptype)>
<cfoutput><select name="sbbox" id="sbbox" class="can" multiple>
<cfloop list="#lstFinds#" index="k" delimiters=",">
<option value="#k#" <cfif #listfindnocase(variables.ptypes,k)#>selected</cfif>>#k#</option>
</cfloop>
</select></cfoutput>
I have a database table with error id and error details for form validation errors.
In my ColdFusion form page, I have a list of error numbers 2,4,7 available. But I want to display errors like "Please enter name" etc.
I want to compare my list of errors with error id's in the database table and display the corresponding error in my form. Please let me know if there is any better way to do it. Thanks in advance!!
<form name = "empform" action="empform.cfm" method="post">
<cfoutput>
<table border="0">
<tr><td colspan="4" align="center" style="padding-bottom:20px;"><h2>Add Employee</h2></td></tr>
<cfif (structKeyExists(rc,"addemp"))>
<cfif rc.result.hasErrors()>
<tr>
<td colspan="4" style="border:2px solid red;">
Please review the following:
<ul>
<cfloop array="#rc.result.getFailureMessages()#" index="message">
<li>#message#</li>
</cfloop>
</ul>
</td>
</tr>
</cfif>
</cfif>
<cfset myArray = rc.result.getFailureMessages()>
<cfset myList = ArrayToList(myArray, ",")>
<cfquery name="qErrorMessages" datasource="#dsn#" >
Select * from ErrorMessages
</cfquery>
<tr>
<td><label><b>Emp Last Name</b></label></td>
<td><input name="lastname" type="text" value="" /></td>
<td><label><b>First Name</b></label></td>
<td><input name="FirstName" type="text" value="" /></td>
</tr>
<tr>
<td><label><b> Emp Birth Date</b></label></td>
<td><input name="birthdate" type="text" value="" /></td>
<td><label><b>Salary</b></label></td>
<td><input name="salary" type="text" value="" /></td>
</tr>
<tr><td style="padding-top:10px;">
<input type="submit" name = "addemp" value ="AddEmp /></td>
</tr>
</table>
</cfoutput>
</form>
I can display errors as shown above
Now I want to show actual messages. I am stuck up here.
My issue is not solved. I am able to loop through the table of errors only. Probably I need to loop through my list of error ids and then I need another loop to look up for the table errorId's to match then display the error.
I got it fixed with the below code.
<cfloop index="ind" list=#mylist#>
<cfquery datasource= "#dsn#" name="emperrors">
Select errorid,errmessage from errorcodes where errorid = #ind#
</cfquery>
#emperrors.errmessage#<br>
</cfloop>
Your question is short on details, but I'd probably query the table with the error messages, convert it to a struct, then drop that struct into a persistent scope that I could then reference later.
Something like:
<cfset errorStruct={}>
<cfloop query="qFormErrorMsgs">
<cfset errorStruct[error_id]=error_msg>
</cfloop>
<cfset application.errorStruct=errorStruct>
Then, when you want to display the error:
<p>Please fix the following error: #application.errorStruct[variables.error_id]#</p>
But that's just one way you might do it. Without more information in your question all you're going to get is guess (if you're lucky).
Alright, your answer detailing code should have been appended to your question via an edit, and still that's really not enough code. How are you determining your errors?
It sounds like your errors are something like this:
Please review the following:
2
3
6.
When what you want is error messages.
An easy way to update this is to load all your messages into an array where the index corresponds to the error codes.
<cfset ErrDetails=ArrayNew()>
<cfset ErrDetails[1]="You didn't enter your first name.">
<cfset ErrDetails[2]="You didn't enter your last name.">
<cfset ErrDetails[3]="You didn't enter a properly formatted birth date.">
<cfset ErrDetails[4]="It appears, from your birthdate, that your age is below 18">
And then, in your cfloop, you can
<cfloop array="#rc.result.getFailureMessages()#" index="message">
<li>#ErrDetails[message]#</li>
</cfloop>
Lastly it sounds like your errorcodes/messages are coming from a database. I'm not really sure that's necessary, but if you really want to keep it that way, that's fine. You can initialize this into the application scope so that you can call it later without rerunning the query, or just put it somewhere in flat text. However, if you want the application scope answer, here's a method.
<cflock scope="application" timeout="5">
<cfif not isDefined("application.ErrDetails")>
<cfquery name="getec">
select ErrID,ErrMessage from ErrorCodes
</cfquery>
<cfset Application.ErrDetails = []>
<cfloop query="getec">
<cfset Application.ErrDetails[ErrID]=ErrMessage>
</cfloop>
</cfif>
<cfset request.ErrDetails = Application.ErrDetails>
</cflock>
Once this is initiated, the cfloop displaying errors as I showed above can use #request.errDetails[message]#
If it's just running in one page, I wouldn't worry about creating an application variable. I'd just hardcode it in, or do a query there with a cfloop similar to above writing to a variables scope variable, not an application variable so the cflock isn't needed.
Unless you also have web based admin creating these rules, I'd probably ditch the table altogether and drop it directly into code, a cfinclude, a udf, or a custom tag.
Since the asker has updated their question with an answer.
Your answer needlessly repeats the query for each iteration.
Try something like this..
<cfquery datasource="#dsn#" name="GetECs">
select ErrorID,ErrMessage from ErrorCodes
where ErrorID in (<cfqueryparam cfsqltype="cf_sql_integer" list="yes" value="#mylist#">)
</cfquery>
<cfoutput query="GetECs">
#currentrow#. #ErrMessage#<br>
</cfoutput>
Notes:
One query is run.
For results, the where ErrorID in (<cfqueryparam cfsqltype="cf_sql_integer" list="yes" value="#mylist#">) is the same as saying where ErrorID in (#mylist#). However, the tag secures your queries against sql injection (the tactic of modifying variables to produce undesirable/malicious results in a query. Read up on cfqueryparam at http://help.adobe.com/livedocs/coldfusion/8/htmldocs/help.html?content=Tags_p-q_18.html
I'm a beginner with ColdFusion and I'm just trying out some basic functions.. I tried to loop over a simple query and put the values in a of a element. As value for the element I tried to set the id of each record of the query. After submiting I tried to read the selected value but I only get
You have chosen #getAll.id#
Here is my Code:
index.cfm
<cfquery datasource="testdb" name="getAll">
select *
from Personen
</cfquery>
<cfform action="chosen.cfm" method="post">
<cfselect name="listPersons">
<cfloop query="getAll">
<option value="#getAll.id#"><cfoutput>#getAll.id# #getAll.name# #getAll.vorname# #getAll.gebdate# <BR></cfoutput>
</cfloop>
</cfselect>
<cfinput type="Submit" name="Senden" value="Senden">
</cfform>
chosen.cfm
<cfoutput>You have chosen #listPersons#</cfoutput>
Can you tell me where I've made the mistake?
You didn't put your value attribute in a cfoutput tag, so it's being processed as #getAll.id# as the key in the struct instead of the value from the query. If you update your cfloop to be a cfoutput your issue will be fixed.
A couple pointers - You should scope the variable on chosen.cfm and you don't need to use cfform a regular form works just fine.
<cfquery datasource="testdb" name="getAll">
select *
from Personen
</cfquery>
<form action="chosen.cfm" method="post">
<select name="listPersons">
<cfoutput query="getAll">
<option value="#getAll.id#">#getAll.id# #getAll.name# #getAll.vorname# #getAll.gebdate#</option>
</cfoutput>
</select>
<input type="Submit" name="Senden" value="Senden">
</form>
chosen.cfm
<cfoutput>You have chosen #form.listPersons#</cfoutput>
Your code works for me with my test database but the value of listPersons on Chosen.cfm is not what I think you intended it to be. I would change the code to the following:
<cfquery datasource="testdb" name="getAll">
select *
from Personen
</cfquery>
<cfform action="chosen.cfm" method="post">
<cfselect name="listPersons">
<cfoutput query="getAll">
<option value="#getAll.id#">#getAll.id# #HTMLEditFormat(getAll.name)# #HTMLEditFormat(getAll.vorname)# #getAll.gebdate#
</cfoutput>
</cfselect>
<cfinput type="Submit" name="Senden" value="Senden">
</cfform>
What I did is I changed your CFLOOP to a CFOUTPUT then removed the CFOUTPUT you had. I also added the HTMLEditFormat functions just in case NAME or VORNAME contain some characters that will not play nice with the display. I assumed ID is numeric and GEBDATE is a date so figured no need on those. I also removed the BR element from your OPTION, not that I thought it was causing an issue but I could not see how that would effect the display either so seemed unneeded. I'd personally would close the OPTION but it is not needed to run. If you ultimate code is not running anything that CFFORM offers then I'd not use it and just use an HTML FORM.
Then on Chosen.cfm I would scope the output:
<cfoutput>#Form.listPersons#</cfoutput>
<cfoutput query="getAll">
#id# #name#
</cfoutput>
You don't need to repeat the query name inside of a cfoutput loop, if with cfoutput you specify the query you are looping over.