I have a single cffunction which returns multiple queries. I'm using 'struct' as my returntype. My question is, how do I use function returns in multiple cfselects. I can get the cfdump to work, but not sure what to put in
cfc
<cffunction name="cfcName" access="remote" returntype="struct">
<cfset var myStruct=StructNew()>
<!---Query1---->
<cfquery name="Query1" datasource="dsn">
SELECT DISTINCT Col1
FROM Table1
ORDER BY Col1
</cfquery>
<!---Query2---->
<cfquery name="Query2" datasource="dsn">
SELECT DISTINCT Col2
FROM table2
ORDER BY Col2
</cfquery>
<cfset myStruct.Query1= Query1>
<cfset myStruct.Query2= Query2>
<cfreturn myStruct>
</cffunction>
<cfinvoke
component="CMPT"
method="cfcName"
returnvariable="Return_cfcName">
</cfinvoke>
cfm,
(Query 1 returns should diplay in this cfselect)
<cfselect name="Select1" required="no" query="?" value="?" display="?" queryPosition="below">
<option value="">ALL</option>
</cfselect>
(Query 2 returns should diplay in this cfselect)
<cfselect name="Select2" required="no" query="?" value="?" display="?" queryPosition="below">
<option value="">ALL</option>
</cfselect>
Any help is appreciated, thanks in advance.
This should do the trick...
<cfselect name="Select1" required="no" query="Return_cfcName.Query1" value="Col1" display="Col1" queryPosition="below">
<option value="">ALL</option>
</cfselect>
<cfselect name="Select2" required="no" query="Return_cfcName.Query2" value="Col2" display="Col2" queryPosition="below">
<option value="">ALL</option>
</cfselect>
Related
I have a ColdFusion 11 component which is supposed to populate a cfselect using bind. However, the select is not populated with the values at all. It shows blank. These are 2 select form controls that I want to relate to each other. A select from one should populate the other with values based on the selection made.
<td>
From IJ:
<cfselect name="im"
id="im"
bind="cfc:BTransfer.Get_Alls()"
display="strTName"
value="city_code"
queryposition="below"
bindonload="true">
<option value="">Select ...</option>
</cfselect>
</td>
<td>
To IJ:
<cfselect
name="toij"
id="toij"
bind="cfc:BTransfer.Get_Ts({city_code})"
value="strTCode"
display="strTName"
queryposition="below">
<option value="">Select ...</option>
</cfselect>
</td>
[b]The component.[/b]
<cfcomponent output="false">
<cffunction name="Get_Alls" access="remote" output="false" returntype="Query">
<cfset var qry_getall = "">
<CFQUERY NAME="qry_getall" DATASOURCE="#dsn#" cachedWithin="#CreateTimeSpan(1,0,0,0)#" >
SELECT T_Code AS strTCode,
ltrim(t_name) AS strTName,
city_code
FROM tblLookupTCity
WHERE blnactive = 1
ORDER BY T_name
</CFQUERY>
<cfreturn qry_getall />
</cffunction>
<cffunction name="Get_Ts" access="remote" output="false" returntype="Query">
<cfset var qry_getall = "">
<cfargument name="city_code" type="numeric" required="true" >
<CFQUERY NAME="qry_getall" DATASOURCE="#dsn#" cachedWithin="#CreateTimeSpan(1,0,0,0)#" >
SELECT T_Code AS strTCode,
trim(T_name) AS strTName,
city_code
FROM tblLookupTCity
WHERE CITY_CODE = '#arguments.city_code#'
AND blnactive = 1
ORDER BY T_name
</CFQUERY>
<cfreturn qry_getall />
</cffunction>
</cfcomponent>
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 three select boxes: State, District, School. The first two work great if I don't have the school, but the school is actually the important part. Without the school select everything works fine. With the school box I get the error:
Bind failed, element not found: pid
CFC
<cfcomponent>
<cfset THIS.dsn="whatever">
<cffunction name="getDistricts" access="remote" returntype="query">
<cfargument name="state" required="yes" hint="The districts are in this state." />
<cfstoredproc datasource="#THIS.dsn#" procedure="getSchoolAndDistrict" returncode="yes">
<cfprocparam cfsqltype="cf_sql_varchar" dbvarname="#mstate" value="#arguments.state#" type="in">
<cfprocresult resultset="1" name="districts">
</cfstoredproc>
<cfreturn districts>
</cffunction>
<cffunction name="getSchools" access="remote" returntype="query">
<cfargument name="state" required="yes" hint="The districts are in this state." />
<cfargument name="pid" required="yes" hint="The district pid." />
<cfstoredproc datasource="#THIS.dsn#" procedure="getSchoolAndDistrict" returncode="yes">
<cfprocparam cfsqltype="cf_sql_varchar" dbvarname="#mstate" value="#arguments.state#" type="in">
<cfprocparam cfsqltype="cf_sql_varchar" dbvarname="#pid" value="#arguments.pid#" type="in">
<cfprocresult resultset="2" name="schools">
</cfstoredproc>
<cfreturn schools>
</cffunction>
</cfcomponent>
CFM
<cfoutput>
<cfform action="#CGI.PATH_INFO#" name="testdistricts" method="post">
<cfselect name="states" query="states"
queryPosition="below"
display="state" value="state">
<option value="">State</option>
</cfselect>
<cfselect name="districts"
bind="cfc:cfcs.getDistricts.getDistricts({states})"
queryPosition="below"
display="name" value="pid" bindonload="no">
<option value="">District</option></cfselect>
<cfselect name="schools"
bind="cfc:cfcs.getDistricts.getSchools({pid})"
queryPosition="below"
display="name" value="pid" bindonload="no">
<option value="">School</option>
</cfselect>
<br> <br>
<cfinput type="submit" name="submit" value="Submit">
</cfform>
</cfoutput>
Your problem is that the Schools select is bound to the value of the selected option instead of being bound to the district control itself...
<cfform action="#CGI.PATH_INFO#" name="testdistricts" method="post">
<cfselect name="states" query="states"
queryPosition="below"
display="state" value="state">
<option value="">State</option>
</cfselect>
<cfselect name="districts"
bind="cfc:cfcs.getDistricts.getDistricts({states})"
queryPosition="below"
display="name" value="pid" bindonload="no">
<option value="">District</option></cfselect>
<cfselect name="schools"
bind="cfc:cfcs.getDistricts.getSchools({districts})"
queryPosition="below"
display="name" value="pid" bindonload="no">
<option value="">School</option>
</cfselect>
<br> <br>
<cfinput type="submit" name="submit" value="Submit">
</cfform>
This is where your problem is
bind="cfc:cfcs.getDistricts.getSchools({districts})"
So I've been using in-line (correct term?) ColdFusion code to run all my pages and have gotten to a point where I think I have a decent understanding of the basics, and want to take the next step. After a lot of cross-referencing, research, and trial and error, I've come up with the following 4 pages of which the intent is to be able to enter a username and password in the form page (crud.cfm), then, after submission, redirect the user to a page which displays the newly entered data, as well as any past entries.
I can do all of this with simple in-line code and an Application.CFM but I want to migrate toward a more OOP/Modular approach going forward, as presently I find myself rewriting/copy-pasting scads of code across several different pages. The error that I get when I submit from 'crud.cfm' is:
"The component attribute in cfinvoke tag has invalid value."
I have tried it without hashes and without the uppercase "A" to no avail. Here is my non-working code:
Application.cfc
<cfcomponent output="false">
<cffunction name="insertrecord" access="public" output="false">
<cfargument name="data" type="struct" required="true">
<cfquery name="create" datasource="test">
INSERT INTO logins(
username,
password)
VALUES(
'trim(form.username)',
'trim(form.password)')
</cfquery>
</cffunction>
</cfcomponent>
crud.cfm
<h3> Enter new user/password </h3>
<cfform name="thisform" method="post" action="procpage.cfm">
Username:<cfinput type="text" name="username" value="">
Password:<cfinput type="password" name="password" value="">
<input type="submit" value="submit">
</cfform>
procpage.cfm
<cfif !StructIsEmpty(form)>
<cfinvoke component="#Application#" method="insertrecord">
<cfinvokeargument name="data" value="#form#">
</cfinvoke>
</cfif>
<cflocation url="resultpage.cfm" addtoken="no">
resultpage.cfm
<cfquery name="read" datasource="test">
SELECT * FROM logins
</cfquery>
<table>
<tr>
<th>LOGIN</th>
<th>USERNAME</th>
<th>PASSWORD</th>
</tr>
<cfloop query="read">
<tr>
<td>#read.login#</td>
<td>#read.username#</td>
<td>#read.password#</td>
</tr>
</cfloop>
</table>
ColdFusion version 8, MSSQL 2005 database.
Thank you all in advance for your help, looking forward to your responses!
Application.cfc is a special file in ColdFusion.
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=AppEvents_01.html
You'll need to name your component something else. Application.cfc is where you put Application events, setup code, etc.
In answer to your question to Miguel, Yes. The application.cfc is called each time a cfm is called. So when you hit the crud.cfm, application.cfc runs. When you hit procpage.cfm application.cfc runs etc..
so you want your procpage.cfm to look more like
<cfif !StructIsEmpty(form)>
<cfinvoke component="functions" method="insertrecord">
<cfinvokeargument name="data" value="#form#">
</cfinvoke>
</cfif>
and your functions.cfc looks more like
<cfcomponent output="false">
<cffunction name="insertrecord" access="public" output="false" returntype="void">
<cfargument name="data" type="struct" required="true">
<cfquery name="create" datasource="test">
INSERT INTO logins(
username,
password)
VALUES(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.username)#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.password)#">
)
</cfquery>
</cffunction>
<cffunction name="readRecord" access="public" returntype="query">
<cfargument name="loginID" type="numeric" required="false" default="0">
<cfquery name="read" datasource="test">
SELECT * FROM logins
where loginID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.loginID#">
</cfquery>
<cfreturn read/>
</cffunction>
</cfcomponent>
resultsPage.cfm
<cfscript>
f = createObject('component','functions');
r= f.readRecord(theIdToPass);
</cfscript>
<table>
<tr>
<th>LOGIN</th>
<th>USERNAME</th>
<th>PASSWORD</th>
</tr>
<cfloop query="r">
<tr>
<td>#r.login#</td>
<td>#r.username#</td>
<td>#r.password#</td>
</tr>
</cfloop>
</table>
You will find that cfqueryparam not only has a small performance boost but will protect you from sql attacks and such, USE IT!! Always.
You also might think about doing arguments for each one expect instead of using struct variables, since writting error trapping for a struct without know what you are expecting to be passed can be pretty frustrating.
Hopefully this can get you off to a positive start with CF!
I have a text field that I want to autosuggest values based on a query. I have a main file along with a separate file (getdata.cfc) that holds my query.
Here is the text field portion of my main file:
<cfinput name="search_query" autosuggest="url:getdata.cfc?suggestvalue={cfautosuggestvalue}" maxResultsDisplay="10" showAutoSuggestLoadingIcon="true" size="10" />
Here is the code in getdata.cfc:
<cfcomponent>
<cffunction name="get_data" access="remote" output="false">
<cfargument name="suggestvalue" required="true">
<cfquery name="get_data" datasource="#application.DSN#">
SELECT DISTINCT myItem
FROM myTable
WHERE myItem LIKE <cfqueryparam value="#suggestvalue#%"
cfsqltype="cf_sql_varchar">
ORDER BY myItem
</cfquery>
<cfif get_data.recordCount eq 1>
<cfreturn ",#get_data.myItem#">
<cfelse>
<cfreturn ValueList(get_data.myItem)>
</cfif>
</cffunction>
</cfcomponent>
The text field shows up fine, but when I type a word no autosuggest values show up. Nothing happens. The text is just displayed as I type it.
Any suggestions? Thank you!
I switched away to using jquery plugins from a lot of CF stuff, but here is an example I have that works in some old production code
<cfinput type="text" name="email" id="email" autosuggest="cfc:cfc.users.lookupEmail({cfautosuggestvalue})" maxresultsdisplayed = "25">
<cffunction name="lookupEmail" access="remote" returntype="array">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(1)>
<!--- Do search --->
<cfquery name="data" datasource="datasource" maxrows="25" cachedwithin="#CreateTimeSpan(0,0,30,0)#">
SELECT distinct email
FROM users
WHERE email LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.search#%">
ORDER BY email
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset ArrayAppend(result, email)>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
maybe this helps
also make sure you have your cfform tags around your form, and make sure that your /cfide folder is mapped to your website.
looking at your code and comparing it... it may be the way your calling the cfc (filename)
try: autosuggest="cfc:getdata.get_data.({cfautosuggestvalue})"