cfgrid - how to sort a column of numbers numerically - coldfusion

I'm using a cfgrid control on Coldfusion 9.01 to display a query recordset with several columns of numbers.
My grid is format="html" and a query as the datasource.
A partial list of my grid columns are as follows:
<cfgridcolumn name="delivery" header="Email Delivery" width="300" />
<cfgridcolumn name="deliveryDate" header="Delivery Date" width="100" />
<cfgridcolumn name="sent" header="Sent" width="50" type="numeric" />
<cfgridcolumn name="Opens" header="Opens" width="50" type="numeric"/>
<cfgridcolumn name="OpenRatio" header="%Opens" width="75" type="numeric" />
The problem I am running into is that when I click on the column heading to sort one of the number columns, the grid is sorting the numbers as text.
9999,
9,
888,
8,
777,
7
etc.
I have the type set as numeric. Is there there anything else I can do to force the grid to sort the columns of numbers in numerically.
UPDATE: As a workaround, I am using bind as the datasource instead of query and the sorting works as expected.

Related

How do I process data in a list in cold fusion 10

I have a form that has 3 rows. A checkbox and two input field per row.
The field names are paid, amount and tranid.
If I tick the checkbox on the second row, and enter data into the other two fields and click submit I have the following;
Listlen is 1.
listgetat(form.paid,1) contains the value assigned to the check box.
the list for amount are 0.00,16.00,0.00
The list for tranid id are "",Test123,"" (nul, value, nul)
Therein is my problem. I can't loop through the list because listlen = 1 and listgetat(form.amount,1) returns 0.00 because the data is in the second list item.
I can't get the value from listgetat(form.paid,2) because I only selected one checkbox, so listgetat(form.paid,1) contains that value.
Clearly my understanding of working with lists is lacking.
This is a payment processing page, where the user selects which outstanding payments have been paid. They enter a bank transaction ID and how much was paid. The number of rows depends on how many payments are outstanding, in this test case there are three.
Can someone please explain how to process the list.
thank you.
The input page; Select only unpaid transactions:
<cfquery name="unpaid" datasource="#Application.datasource#">
select * from payments where pflag=0
</cfquery>
The input page; The three relevant fields;
<cfif #unpaid.recordcount# gt 0>
<cfoutput query="unpaid">
<tr>
<td><span class="pagetext">
<input type="checkbox" name="paid" id="paid" value="#idpayments#" />
</span></td>
<td class="pagetext">#idpayments#</td>
<input name="tranid" type="text" id="tranid" size="15" maxlength="40" /></td>
<td align="right">
<span class="pagetext">$<input name="amount" type="text" id="amount" size="7" maxlength="7" value="#ap#" />
</span></td>
</tr>
<cfset total=#total#+#ep#>
</cfoutput>
</cfif>
The processing code..
<cfloop from="1" to="#Listlen(FORM.amount)#" index="i">
<cfif #ListGetAt(FORM.amount,i)# gt 0>
<!--- update the payment --->
<cfquery name="updtrec" datasource="#Application.datasource#">
update payments set pflag=1,
ap=#ListGetAt(FORM.amount,i)#,
datepaid='#newdate#',
<cfif #len(ListGetAt(FORM.tranid,i))# gt 0>, ptranid=#ListGetAt(FORM.tranid,i)#</cfif>
where idpayments=#ListGetAt(FORM.paid,i)#
</cfquery>
</cfif>
</cfloop>
A description of the issue is helpful, but you should also include some code along with it. The absolute smallest amount of code needed to illustrate the issue, omitting any irrelevant stuff like css. Here's a good example for this question:
<form ...>
Row #1
<input type="checkbox" name="paid" value="111">
Amount <input type="text" name="amount">
TransId <input type="text" name="transid">
<br>
Row #2
<input type="checkbox" name="paid" value="222">
Amount <input type="text" name="amount">
TransId <input type="text" name="transid">
<br>
Row #3
<input type="checkbox" name="paid" value="333">
Amount <input type="text" name="amount">
TransId <input type="text" name="transid">
</form>
Clearly my understanding of working with lists is lacking.
The problem isn't your understanding of lists, but of how form fields are handled. The code mistakenly assumes all three form variables will always contain a list of three values. They won't. While same name'd fields get converted into a comma separated list when submitted, not all form fields submit a value and some values are effectively discarded:
A checkbox only submits a value IF it's checked
An enabled text field always submits a value, but that value may be an empty string. Historically, most list functionality in CF ignores empty strings
So the form variables aren't guaranteed to always contain a list of three values. It may be less if some of the text fields are empty or boxes aren't checked (form.paid won't even exist at all if none of the boxes are checked). That's why the list functions aren't working as you expected.
Assuming you have a unique numeric value like an "id" for each row, give all checkboxes the same name and use the numeric id as the checkbox value. Then use the numeric "id" as part of the associated text field names, in order to group each row of fields together
<input type="checkbox" name="paid" value="111">
<input type="text" name="amount_111">
<input type="text" name="transid_111">
...
<input type="checkbox" name="paid" value="222">
<input type="text" name="amount_222">
<input type="text" name="transid_222">
...
When submitted, form.paid will contain a list of the selected id's. Loop through the list of id's and use the current "id" to extract the amount and transid values:
for (....) {
amount = form["amount_"& currentId];
transid = form["transid_"& currentId];
}

CFGrid combobox list getting mixed up with other grids in the page

Currently we have ColdFusion 2016 Update 1 installed on our deployed server. After we upgraded our CF version from 9 to 2016, all cfgrids combobx columns started behaving a bit strange. Grid combobox columns are not displaying the exact values defined in cfgridcolumn values and valuesdisplay list. We have some links on the grid that opens up a pop-up with cfgrid. This grid combobox list data is getting mapped to the parent grid combobox list.
For ex: If the parent grid second column is a combobox and values="true,false" and the pop-up grid second column combobox values="FE,TSE,TS", If I try to edit pop-up grid second column, true/false is appearing in the combobox list.
Strangely this is happening with all the grids that have editable combobox columns. Can anyone please help me with this issue?
Grids settings is something like:
<cfset gridArgs = structNew()>
<cfset gridArgs.name = "LoansGrid">
<cfset gridArgs.pageSize = 20>
<cfset gridArgs.format = "html">
<cfif SERVER.ColdFusion.ProductVersion lt 9>
<cfset gridArgs.width = "99%">
</cfif>
<cfset gridArgs.autowidth = "no">
<cfset gridArgs.bindOnLoad = "true">
<cfset gridArgs.bind = "cfc:XXX.MVP.components.Manager.getRecords({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{Filter})">
<cfset gridArgs.stripeRows = true>
<cfset gridArgs.selectColor = "##D9E8FB">
<cfset gridArgs.selectmode = "edit">
<cfset gridArgs.onchange = "cfc:XXX.MVP.components.Manager.editRecord({cfgridaction},{cfgridrow},{cfgridchanged})">
<style>
td div, table div, form div { margin:0; } .x-grid-header { margin:0; } .x-grid-hd-row td { line-height:normal; }
</style>
<cfform name="EEEForm">
<cfinput type="hidden" name="Filter" value="#id#">
<cfgrid attributeCollection="#gridArgs#">
<cfgridcolumn name='Links' header='Links' display="true" width="170" select="no">
<cfgridcolumn name='Record_ID' header='Record ID' display="false" select="no">
<cfgridcolumn name="ID" header="ID" display="false" select="no">
<cfgridcolumn name="Number" header="Number" display="true" bold="yes">
<cfgridcolumn name="IncludeInRun" header="Include in Run" display="true" values="1,0" valuesdisplay="True,False">
<cfgridcolumn name="Status" header="Status" display="true">
<cfgridcolumn name="LastName" header="Last Name" display="true">
<cfgridcolumn name="ProductType" header="Product Type" display="true" values="#productType#" valuesdisplay="#productType#">
<cfgridcolumn name="PropertyType" header="Property Type" display="true" values="#propertyType#" valuesdisplay="#propertyType#">
........
</cfgrid>
</cfform>

try to get my cfdiv to load on the same page

I have a page that provide some information and a cfselect tag.
<cfform name="selectrate" method="post" format="html">
<cfselect name="rateid" query="getrate" value="rateid" display="ratecode" />
</cfform>
<cfajaximport tags="cfform">
<cfdiv id="rateDiv" bind="url:testniva_3.cfm?rateid={rateid}" style="height:1500" bindonload="true">
For each rateid that is selected the cfdiv will call on testniva_3.cfm which provide information for that rateid. The testniva_3.cfm has a <cfsavecontent> tag that will calculate the grandtotal for the cfgrid in the same page. The testniva_3.cfm has this code:
<cfform name="display" format="flash">
<cfgrid name= "cart" query="getdtls" selectmode="edit" width="580">
<cfgridcolumn name="chargename" header="Charge Type" dataalign="right" select="No" >
<cfgridcolumn name="price" header="price"type="numeric" dataalign="right" select="No" >
<cfgridcolumn name="quantity" header="Quantity" type="numeric" dataalign="right" >
</cfgrid>
<cfinput type="Button" name="calculateBtn" value="Calculate Order" onclick="#calculateTotal#">
<cfinput type="Text" name="total" disabled="true" label="Total $" size="5">
</cfform>
The cfdiv seems to bind with the cfselect tag, because when I change the option in cfselect, the data in testniva_3.cfm page also changes, however, instead of remain on the page with all the information and the select option, it give me an error: Error processing JavaScript in markup for element rateDiv: [Enable debugging by adding 'cfdebug' to your URL parameters to see more information
then when I click OK, it refreshs the page and just give me the testniva_3.cfm page without all the information and select option of the main page. If I change the format of the cfgrid on the cfform in the testniva_3.cfm page to html, then the grid refresh the data without any problem, however, my <cfsavecontent>#calculateTotal# will not work with html format.
I am not sure what went wrong, and how to fix it. Any one have any ideas? I would really appreciated.
Thank you.

coldfusion - how to loop the value that was passed from getElementById in the same page?

I want to loop the selected number from the list (cfselect). I tried getElementById but only able to display it on the same page. I cannot pass this number to the loop. Can someone help me? Thank you.
function item()
var a = document.formName.numList.selectedIndex;
document.getElementById('i').value = document. family.tBro.options[a].value;
var n=document. family.tBro.options[a].value;
<!----OTHER INPUT TEXT BOXES --->
<cfform name="family" action="complete.cfm" method="post">
How many brothers do you have?
<cfselect name="tBro" onChange="item();" required="yes">
<option value="1"> 1</option>
<option value="2"> 2</option>
<option value="3"> 3</option>
<option value="4">4</option>
</cfselect>
<!---DISPLAY THE SELECTED CHOICE from getElementById--->
Total number of brothers: <cfinput type="text" name="i" id="i">
<!---LOOP x amount of time from selected choice above.
For example, if 2 is selected, the below info will display two times
--->
<cfinput type="text" name="firstname" required="yes">
<cfinput type="text" name="lastname" required="yes">
<cfinput type="text" name="Age" required="yes">
<cfinput type="text" name="Ocupation" required="yes">
<!--- END LOOP--->
Tip: state what you're trying to accomplish, rather than the implementation. I had to reread it a few times to understand your need, in which case what your implementation isn't really a good fit.
You're trying to pass JavaScript to CFM code: that's not the way it works. ColdFusion is rendered on the server; JavaScript is rendered on the client. At the moment when item() is called, ColdFusion has finished all of its rendering; you can't effect a CF loop with the result of item().
Without a really complex AJAX solution, you have 2 choices:
refresh the browser when init() is called where you pass dropdown value in the url (not good, as you'd lose state of other form fields)
use something else like jQuery to render your dynamic list of text fields. This is probably the best approach, and a common one. The downside of this is you'll need to implement things like "required" in jQuery, which isn't a big deal, and a common use case.

Coldfusion Looping over query

I have a query result something like
ID IDParent Name Title
--------------------------------------
1 -1 Test1 Test1_Title
2 -1 Test2 Test2_Title
3 -1 Test3 Test3_Title
4 2 SubTest2 SubTest2_Title
5 2 SubTest3 SubTest3_Title
6 2 SubTest4 SubTest4_Title
7 3 SubTest6 SubTest8_Title
8 3 SubTest8 SubTest10_Title
with menu and submenu options.I want to loop over the menu option where IDParent is -1 and after each menu Item where IDParent -1 I would like to loop its child items.
Does coldfusion provides such grouping when looping over queries?
Thanks
CFOUTPUT supports query groupings as well.
<cfquery name="qGetTests" datasource="#DSN#">
SELECT ID, IDParent, Name, Title
FROM Menu
ORDER BY IDParent, Name
</cfquery>
<cfoutput query="qGetTests" group="IDParent">
#IDParent#<br />
<cfoutput>
#ID# #Name# #Title#<br />
</cfoutput>
</cfoutput>
That's pretty easy with Query of Queries (QoQ) and a little recursion:
<!-- database query, sorted in the way you want to display the results -->
<cfquery name="Menu" datasource="#YourDSN#">
SELECT ID, IDParent, Name, Title
FROM Menu
ORDER BY Name
</cfquery>
<!-- output menu -->
<cfset OutputQueryRecursive(Menu, -1)>
<!-- support function -->
<cffunction name="OutputQueryRecursive">
<cfargument name="BaseQuery" type="query" required="yes">
<cfargument name="ParentId" type="numeric" required="yes">
<cfquery name="CurrLevel" dbtype="query">
SELECT * FROM BaseQuery WHERE IDParent = #ParentId#
</cfquery>
<cfif CurrLevel.RecordCount gt 0>
<ul>
<cfoutput query="CurrLevel">
<li id="menu_#ID#">
<span title="#HTMLEditFormat(Title)#">#HTMLEditFormat(Name)#</span>
<cfset OutputQueryRecursive(BaseQuery, ID)>
</li>
</cfouptut>
</ul>
</cfif>
</cffunction>
If you have any control of the SQL generating that query result, you could consider getting the DB to get you the data back in the right format in the first place. Approaches for Oracle and SQL server are covered here and there's some options for mySQL here
If your menu data is always going to be small, then there'll be no problem with Tomalak's solution, but if you're ever going to have large numbers of menu items then I'd test that it still performs ok.
consider qTestQuery contains the values
<cfset qTestQuery1 = qTestQuery>
<cfloop query="qTestQuery">
<cfif qTestQuery.IDParent eq -1>
<span class="main-menu">#qTestQuery.name#</span>
</cfif>
<cfset local.parentId = qTestQuery.IDParent>
<cfloop query="qTestQuery1">
<cfif qTestQuery1.IDParent eq local.parentId>
<span class="sub-menu">#qTestQuery1.name#</span>
</cfif>
</cfloop>
</cfloop>