Coldfusion: specific action after selecting an option in select - forms

I have following code:
<cfif session.language is ("DE")>
<cfset bl=ValueList(getContent.G,",")>
<cfelseif session.language is ("FR")>
<cfset bl=ValueList(getContent.H,",")>
<cfelseif session.language is ("EN")>
<cfset bl=ValueList(getContent.I,",")>
</cfif>
<cfset tags = sizes />
<cfset bltags = bl />
<cfset tagArray = arrayNew(1) />
<cfset tagArrayDATA = arrayNew(1) />
<cfloop list="#tags#" index="tag" delimiters=",">
<cfif not ArrayFindNoCase(tagArray,tag)>
<cfset arrayAppend(tagArray, tag) />
</cfif>
</cfloop>
<cfloop list="#bltags#" index="tag" delimiters=",">
<cfif not ArrayFindNoCase(tagArrayDATA,tag)>
<cfset arrayAppend(tagArrayDATA, tag) />
</cfif>
</cfloop>
<cfoutput>
<cfif isdefined("tagArray") AND arraylen(tagArray) GT 1>
<form name="frmsize" id="frmsize" action="/index.cfm?showusage" method="post">
<cfif isdefined("tagArray") AND arraylen(tagArray) GT 1>
<div>
<select name="valuesize">
<option value="">Choose your option</option>
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<option value="#tagArray[i]#">#tagArray[i]#
<cftry>
#tagArrayDATA[i]#
<cfcatch>
</cfcatch>
</cftry>
</option>
</cfloop>
</select>
</div>
</cfif>
</form>
</cfif>
</cfoutput>
My goal is to send a value from tagArrayDATA[i] via link.
It should look like that:
<form name="frmsize" id="frmsize" action="/index.cfm?showusage&valueArrayData="#tagArrayDATA[i]#" method="post">
I don't know how to manage that because the cfloop is below the action attribute of the form.

You can't really do what you are trying to do with server side code alone as far as I can tell. But you have a couple of options. One easy one is to just Javascript to update the action when the select is changed.
The other option is to put both values in the select and parse on the end.
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<option value="#tagArray[i]#-#tagArrayDATA[i]#">
#tagArray[i]# #tagArrayDATA[i]#
</option>
</cfloop>
Then when you are parsing the data just do:
<cfset data = listToArray(FORM.valuesize,'-') />
<!-- data[1] will be the selected value of #tagArray[i]# -->
<!-- data[2] will be the selected value of #tagArrayData[i]# -->
<!-- This assumes the - will never be actually in the data, you could use a different separator -->
My guess is they are both strings and this should work, though I have no idea why you have a try/catch in the select part of your code, probably look at a better way of doing that. If you really need that, I would clean it up as.
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<cfset data = '' />
<cftry>
<cfset data = tagArrayData[i] />
<cfcatch></cfcatch>
</cftry>
<option value="#tagArray[i]#-#data#">
#tagArray[i]# #data#
</option>
</cfloop>
Though if you are processing the data on the other end, I would make sure all the data is either in the FORM or the URL scopes but not mix. I would be pissed to have to parse some form data in the FORM scope and other data in the URL scope.

Related

ColdFusion dateformat wrong format

I have an input text where I get the date:
<input type="text" name="myDate" />
After submitting the form, I save this date into the database doing a dateformat:
#DateFormat(myDate, "yyyy-mm-dd")#
If the user enters: 02/19/1948, it saves correct: 1948-02-19.
But if the user enters: 02191948, it saves: 7901-05-07. Why? Does anyone know how I can fix it?
Thanks
ColdFusion's DateFormat() expects a valid date representation. ColdFusion is very sloppy when it comes to what type of input is considered valid. Safe date inputs are ODBC literals and most of ISO 8601. Beware of format pitfalls like mm/dd and dd.mm and avoid them altogether, if possible.
What you want to use is LSParseDateTime(). It allows you to specify the locale and format you expect and make ColdFusion parse a date object based on the input. It's not fail-safe though, meaning you have to try-catch it in case the input doesn't match at all. There is a fail-safe LSIsDate(), which tells you if the input is considered valid in the specified locale. But either way, it's a game of format detection. Having fixed <select> tags for month, day and year is the easiest way to avoid issues.
Loose demo for localized date input:
<cfset myLocale = "en_US">
<cfset myDateFormat = "yyyy-mm-dd">
<cfset dateByInput = "">
<cfset errorReason = "">
<cfif structKeyExists(FORM, "myDate")>
<cfif lsIsDate(FORM["myDate"], myLocale)>
<cftry>
<cfset dateByInput = lsParseDateTime(FORM["myDate"], myLocale, myDateFormat)>
<cfcatch>
<cfset errorReason = ("Your input is invalid. Please enter in the following format: " & myDateFormat)>
</cfcatch>
</cftry>
<cfelse>
<cfset errorReason = ("Your input is invalid. Please enter in the following format: " & myDateFormat)>
</cfif>
</cfif>
<cfset dateByInputIsValid = isDate(dateByInput)> <!--- note: it's sufficient to use the unlocalized date check here, since dateByInput is either not valid at all or a (universal) date object --->
<cfif dateByInputIsValid>
<!--- store date input in database --->
<cftry>
<cfset myDatasource = "exampleDS">
<cfquery datasource="#myDatasource#">
INSERT INTO `myDatabase`.`myTable` ( `myDateColumn` ) VALUES (
<cfqueryparam value="#dateByInput#" cfSqlType="CF_SQL_TIMESTAMP">
)
</cfquery>
<cfcatch>
<cfset errorReason = "Oh noes, something went wrong attempting to save your input.">
</cfcatch>
</cftry>
</cfif>
<cfoutput>
<cfif dateByInputIsValid>
<p>Date input valid: #lsDateFormat(dateByInput, myDateFormat, myLocale)#</p>
<cfif len(errorReason)>
<p>#errorReason#</p>
<cfelse>
<p>Input successfully stored in database.</p>
</cfif>
<cfelse>
<cfif len(errorReason)>
<p>#errorReason#</p>
</cfif>
<form method="post">
<input type="text" name="myDate" />
<button type="submit">send</button>
</form>
</cfif>
</cfoutput>

How to get the value of radio button in ColdFusion?

I can't find a simple tutorial to help me do this task. Basically I need to assign the value of radio button and pass it to the next page through session. This is my code for the radio button input.
<input type="radio" name="statReqYN" id="statReqYN-0" value="Yes" checked="checked"> Yes
<input type="radio" name="statReqYN" id="statReqYN-1" value="No"> No
After that, I will set the value of button:
<cfif isdefined("form.newProdYN") and form.newProdYN is "No">
<cfset form.newProdNY = "No">
</cfif>
Lastly, I will pass it to the next page of the same session through the submit button:
<cfif not arrayLen(errors)>
<cfset session.checkout.input = {
newProdNY=form.newProdNY}>
<cflocation url="formcomplete.cfm" addToken="false">
</cfif>
But when I try to get the value with #session.checkout.input.newProdYN# in html, the result is undefined. Can anyone help me solve this problem?
Your question isn't very clear as there are variables that are not being shown in your code.
Generally, with radio and checkbox fields, your receiving form should have a default value set. I do this by doing something along the lines of:
<cfparam name="FORM.statReqYN" default="no">
This way you can always use the variable. So in your case, I would have this as the whole template:
<cfparam name="form.statReqYN" default="No">
<cfparam name="form.newProdYN" default="Yes">
<form action="" method="post">
<input type="radio" name="statReqYN" id="statReqYN-0" value="Yes" checked="checked"> Yes
<input type="radio" name="statReqYN" id="statReqYN-1" value="No"> No
<button type="submit" name="newProdYN" value="Yes">Submit</button>
</form>
<cfif form.newProdYN IS 'Yes'>
<cfset session.checkout.input.newProduNY = form.newProdYN >
<cfset session.checkout.input.statReqYN = form.statReqYN >
<cflocation url="formcomplete.cfm" addToken="false">
</cfif>
I hope this makes a bit more sense?

ColdFusion form: how to refer to a selection from a binding?

I am not sure if I am thinking about this correctly. I am still new to ColdFusion. I am creating a form which uses binding for the user to select a category and then a specific service. The code for the binding works great. The problem is that now I need to pull some additional information from the service to refer to another field. For example, if the service selected has a "Y" under additional info needed. A field will show that additional information is needed (this field is not changeable)
Originally I thought I could do something like regenerate the same query I did to pull the list of services and just refer to the service type that is selected. Yet I keep getting an error that the field is not defined. Here is the code that I am trying to make it work.
UPDATED: I got it to work I changed the code below the only problem is that I can not get the "Y" to display I get [object Object] instead. Any advice on how to display the text with use of cfinput?
CFC:
<!--- Get array of Catagory Description types --->
<cffunction name="cat_description" access="remote" returnType="array">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="getServiceCat" datasource="Some Database">
select distinct 2 AS SortBy, CATG_NAME
from some table
UNION
select 1 AS SortBy, '' AS CATG_NAME
from Some table
order by SortBy
</cfquery>
<!--- Convert results to array--->
<cfloop index="i" from="1" to="#getServiceCat.recordcount#">
<cfset result[i][1]=getServiceCat.CATG_NAME[i]>
<cfset result[i][2]=getServiceCat.CATG_NAME[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
<!--- Get Service Type by Cat description type --->
<cffunction name="getServiceType2" access="remote" returnType="array">
<cfargument name="CATG_NAME" type="string" required="true">
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="getServiceType2" datasource="Some Database">
select 1 AS SortBy, '' AS SRTY_BNR, '' AS SRTY_NAME
from Some table
UNION
select distinct 2 AS SortBy, SRTY_NBR, SRTY_NAME
from Some Table
where CATG_NAME = <cfqueryparam value="#ARGUMENTS.CATG_NAME#"
cfsqltype="cf_sql_varchar">
order by SortBy
</cfquery>
<cfloop index="i" from="1" to="#getServiceType2.recordcount#">
<cfset result[i][1]=getServiceType2.SRTY_NAME[i]>
<cfset result[i][2]=getServiceType2.SRTY_NAME[i]>
</cfloop>
<cfreturn result>
</cffunction>
<!---Updated below table into CFC to pull information depending on what is pulled
from category and service type--->
<cffunction name="getLR" access="remote" returnType="query">
<cfargument name="SRTY_NAME" type="string" required="true">
<cfset var data="">
<!---Query to get "Y"--->
<cfquery name="lr_required" datasource="Some Datebase">
select distinct LAB_REL_NTFN_FLAG
from some table
where SRTY_NAME = <cfqueryparam value="#ARGUMENTS.SRTY_NAME#"
cfsqltype="cf_sql_varchar">
</cfquery>
<cfreturn lr_required>
</cffunction>
Here is the code within the form:
<TR id="serv_ty" style="display: inline;">
<td align="left" nowrap><label>Service Type:</label></td>
<td>Select Category:
<cfselect name="catdesc"
bind="cfc:servicetype2.cat_description()"
bindonload="true"/><br />
</td>
</TR>
<tr id="serv_ty2" style="display: inline;">
<td></td>
<td>Select Service:
<cfselect name="service_type"
bind="cfc:servicetype2.getServiceType2({catdesc})"
bindonload="false"/>
</td>
</tr>
This is the form code to use the bind which works but will not display the DATA:
<tr id="lr_verify" style="display: inline;">
<td></td>
<td>Additional Info Reuired:
<cfinput
name="lr_needed"
bind="cfc:servicetype2.getLR({service_type})"
bindonload="no"
disabled="disabled"
display="LAB_REL_NTFN_FLAG"/></td>
</tr>
Any advice on how to get it to display or if I should use a different CF statement with the bind to get the correct display. Thanks in advnace for your help on this.

Is there an easier way to manipulate checkboxes in coldfusion?

Basically, I have stored information in a database field and I want to display it again through a form.
The original form has the same checkboxes but they are always empty. The user can check the boxes off and the values are put into the database.
Graduate Courses: Fall? Spring? Summer? Stored as a list in a column named grad. (F, M, S)
They have the option to save this lovely form as a draft. When they come back to the draft I need to display what they might have already checked.
<cfif listContains(#grad#, "F") is not 0>
<input type="checkbox" name="grad" id="grad" value = "F" checked />
<cfelse>
<input type="checkbox" name="grad" id="grad" value = "F" />
</cfif>
<cfif listContains(#grad#, "S") is not 0>
<input name="grad" type="checkbox" id="grad" value = "S" checked />
<cfelse>
<input name="grad" type="checkbox" id="grad" value = "S" />
</cfif>
<cfif listContains(#grad#, "M") is not 0>
<input name="grad" type="checkbox" id="grad" value = "M" checked />
<cfelse>
<input name="grad" type="checkbox" id="grad" value = "M" />
</cfif>
Is there an easier method to doing this with cfform code?
Just curious. :)
I do it like this, as I don't really use <cfform>:
<cfloop list="F,S,M" index="g">
<input type="checkbox" name="grad" id="grad_#g#" value="#g#" #CheckedIf(ListFind(grad, g) gt 0)# />
</cfloop>
<!--- ... --->
<cfscript>
function CheckedIf(expression) {
if (arguments.expression) return 'checked="checked"';
return "";
}
</cfscript>
But the ColdFusion docs state:
[since] ColdFusion MX: Changed the cfform tag
preserveData attribute behavior: if it
is set to True, ColdFusion checks
radio and check box values only if
their value matches the posted value
for the control.
So yes, <cfform> can help you with this. Use <cfparam name="FORM.xyz" default="foobar"> to emulate the "posted value" for normal requests.

ColdFusion auto select option

What is the best way to automatically set a selected item for a select/option element on post-back? Here's the way we're currently doing it:
<select id="grade" name="grade">
<option value="A"<cfif form.grade = 'A'> selected="selected"</cfif>>A</option>
<option value="B"<cfif form.grade = 'B'> selected="selected"</cfif>>B</option>
<option value="C"<cfif form.grade = 'C'> selected="selected"</cfif>>C</option>
<option value="D"<cfif form.grade = 'D'> selected="selected"</cfif>>D</option>
<option value="F"<cfif form.grade = 'F'> selected="selected"</cfif>>F</option>
</select>
Is there a cleaner or easier way to do this with ColdFusion? Thanks in advance!
In my opinion, one of the best ways to go is to use a CFSelect:
<cfquery name="getGrades" datasource="#application.dsn#">
select gradeLetter from Grades
</cfquery>
<cfselect
name="grade"
query="getGrades"
display="gradeLetter"
value="gradeLetter"
selected="#form.grade#" />
Like this:
<cfsavecontent variable="GradeOptions">
A:A
B:B
C:C
D:D
F:F
</cfsavecontent>
<select id="grade" name="grade">
<cfloop index="CurOpt" list="#trim(GradeOptions)#" delimiters="#Chr(10)#">
<option value="#ListFirst(CurOpt,':')#"<cfif form.grade EQ ListFirst(CurOpt,':')> selected="selected"</cfif>>#ListRest(CurOpt,':')#</option>
</cfloop>
</select>
That assumes you always have separate value:label information - if your value and label are always the same, you can do this:
<cfsavecontent variable="GradeOptions">
A
B
C
D
F
</cfsavecontent>
<select id="grade" name="grade">
<cfloop index="CurOpt" list="#trim(GradeOptions)#" delimiters="#Chr(10)#">
<option<cfif form.grade EQ CurOpt> selected="selected"</cfif>>#CurOpt#</option>
</cfloop>
</select>
You could also do this with an array of structs.
<cfparam name="form.grade" default="C">
<cfset mydata = [{grade="A",value="A"},{grade="B",value="B"},{grade="C",value="C"},{grade="D",value="D"},{grade="F",value="F"}]>
<cfoutput>
<select id="grade" name="grade">
<cfloop array="#mydata#" index="i">
<option value="#i['value']#"<cfif form.grade EQ i['grade']> selected="selected"</cfif>>#i['value']#</option>
</cfloop>
</select>
</cfoutput>
using cfscript with functions
<cfscript>
Function setSelected(val1, val2){
if (val1 EQ val2)
{
Return 'selected="selected"';
}
else
{
Return '';
}
}
</cfscript>
<select id="grade" name="grade">
<option value="A" #setSelected('A', form.grade)#>A</option>
<option value="B" #setSelected('B', form.grade)#>B</option>
<option value="C" #setSelected('C', form.grade)#>C</option>
<option value="D" #setSelected('D', form.grade)#>D</option>
<option value="F" #setSelected('F', form.grade)#>F</option>
</select>
What about this?
<cfparam name="form.grade" default="A">
<cfoutput>
<select id="grade" name="grade">
<cfloop index="code" from="65" to="90">
<option value="#Chr(code)#"<cfif form.grade EQ Chr(code)> selected="selected"</cfif>>#Chr(code)#</option>
</cfloop>
</select>
</cfoutput>
A bit tricky, yeah :)
You know, it may be unpopular to say so, but the solution that you originally outlined in the question is the best.
It's simple, it's easy to see what is being done, and it's not trying to be tricky just to be tricky.
Sometimes you just need to wear gloves
http://thedailywtf.com/Articles/The_Complicator_0x27_s_Gloves.aspx
To expand on my other answer, what you should be doing is properly separating your data from your interface, by storing the grades in your database, and using code similar to:
<cfset GradeOptions = Grades.readAvailable() />
<select id="grade" name="grade">
<cfloop query="GradeOptions">
<option value="#GradeCode#"
<cfif Form.Grade EQ GradeCode>selected="selected</cfif>
>#GradeCode# - #GradeDesc#</option>
</cfloop>
</select>
(Again, if grades are only to be treated as a single letter, the values can be provided in a simple list/array rather than query.)
The key thing is, you can change your grade structure without having to change your interface, and likewise updating the interface doesn't require you to know what the grades are.
To be honest I can't see how any of these are better than a corrected version of your initial pass (below)
<select id="grade" name="grade">
<option value="A"<cfif form.grade EQ "A"> selected </cfif> >A</option>
<option value="B"<cfif form.grade EQ "B"> selected </cfif> >B</option>
<option value="C"<cfif form.grade EQ "C"> selected </cfif> >C</option>
<option value="D"<cfif form.grade EQ "D"> selected </cfif> >D</option>
<option value="F"<cfif form.grade EQ "F"> selected </cfif> >F</option>
</select>
It is simple, clean and understandable.
If you just feel a need to be slicker and are going to be doing a lot of UI manipulation invest some time in jQuery. Study Ray Camden's jQuery and CF Posts and Ben Nadel's Javascript and CF Posts and soon this will be second nature...
<script type="text/javascript">
jQuery(document).ready(function() {
$("#grade option[value='<CFOUTPUT>#FORM.Grade#</CFOUTPUT>']")
.attr('selected', 'selected');
});
</script>
<select id="grade" name="grade">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
<option value="F">F</option>
</select>
Sure, it's wackier looking than some of the other options here but amazingly powerful at solving problems that CF just isn't good at once you learn it (trust me, it will quickly make sense and you will wonder how you ever did client UI code without it).
Learn any of the popular JavaScript libraries and your ColdFusion client side code will become dramatically more elegant and powerful.