How to have autocomplete ignore multiples? - coldfusion

Hello I have autocomplete set up like this:
index.cfm
<!--- A simple form for auto suggest --->
<cfform action="autosuggest.cfm" method="post">
Park Name:<br />
<cfinput type="text" name="parkname" size="50" autosuggest="cfc:autosuggest.findPark({cfautosuggestvalue})" autosuggestminlength="1" maxresultsdisplayed="10" /><br /><br />
</cfform>
and autosuggest.cfc
<cfcomponent output="false">
<!--- Lookup used for auto suggest --->
<cffunction name="findPark" access="remote" returntype="string">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var local = {} />
<!--- Query Location Table --->
<cfquery name="local.query" datasource="#application.datasource#" >
select FirstName
from Users
where FirstName like <cfqueryparam cfsqltype="cf_sql_varchar" value="#ucase(arguments.search)#%" />
order by FirstName
</cfquery>
<!--- And return it as a List --->
<cfreturn valueList(local.query.FirstName)>
</cffunction>
</cfcomponent>
What I need it to do is ignore multiples. Instead of having this: Dave, Jack, Jack, Jack, Chet. It should only do this: Dave, Jack, Chet. How would I go about doing that?

You need to use SELECT DISTINCT in your query.
<cfquery name="local.query" datasource="#application.datasource#" >
select DISTINCT FirstName
from Users
where FirstName like <cfqueryparam cfsqltype="cf_sql_varchar" value="#ucase(arguments.search)#%" />
order by FirstName
</cfquery>

Related

ColdFusion cfselect bind not working

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>

Finding images not referenced in a DB table

I get a query of all the files (images) in a directory
<cfset local.teamBase = "#GetDirectoryFromPath(GetBaseTemplatePath())#teamlogo\">
<cfdirectory action="LIST" directory="#local.teamBase#" name="rc.qryTeamLogo">
I later loop over all these filenames, skipping those that are in use
<select name="Logo" <cfif deleted>disabled="disabled"</cfif>>
<option></option>
<cfloop query="rc.qryTeamLogo">
<cfif name EQ mylogo>
<option value="#name#" selected>#name#</option>
<cfelseif request.objTeam.isUsed(name) EQ 1 OR name EQ "thumbs.db">
<!--- Do not show --->
<cfelse>
<option value="#name#">#name#</option>
</cfif>
</cfloop>
</select>
The isUsed() function looks like
<cffunction name="isUsed" returntype="boolean" output="false">
<cfargument name="logo" required="true" type="string">
<cfquery name="qryUsed" datasource="#application.DSN#">
SELECT logo
FROM CCF.team
WHERE logo = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#arguments.logo#">
AND Deleted = 0
</cfquery>
<cfif qryUsed.recordcount EQ 0>
<cfreturn false>
</cfif>
<cfreturn true>
</cffunction>
The problem with this is as more and more files get added, this gets slower and slower.
What I would really like a single query that can assemble the whole thing
You can run one query before your select box
<cfquery name="qryLogos" datasource="#application.DSN#">
SELECT logo
FROM CCF.team
WHERE logo IN (<cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#valueList(rc.qryTeamLogo.name)#" list="true">)
AND Deleted = 0
</cfquery>
Then set all those logo's into an array and add thumbs.db too, so you have one less check to do.
<cfset allLogs = listToArray(valueList(qryLogos.logo))>
<cfset arrayAppend(allLogs,'thumbs.db')>
and then change your elseif to this
<cfelseif arrayFind(allLogs,name)>
<!--- don't display --->
Load the file information into XML. Shread the XML into a table and JOIN on that.
<cfset local.teamBase = "#GetDirectoryFromPath(GetBaseTemplatePath())#teamlogo\">
<cfset local.qryTeamLogo = DirectoryList(local.teamBase, false, "query")>
<cfsavecontent variable="local.xmlTeamLogo">
<ul class="xoxo">
<cfoutput query="local.qryTeamLogo">
<li><code>#xmlformat(name)#</code></li>
</cfoutput>
</ul>
</cfsavecontent>
<cfquery name="local.qryResult">
DECLARE #xmlTeamLogo xml = <cfqueryparam cfsqltype="CF_SQL_varchar" value="#local.xmlTeamLogo#">
SELECT Value AS Name
FROM dbo.udfXOXORead(#xmlTeamLogo)
WHERE NOT Value IN (
SELECT Logo
FROM CCF.Team WITH (NOLOCK)
WHERE Deleted = 0
)
</cfquery>
The Table Valued Function
create function [dbo].[udfXOXORead](#xmlData xml)
returns #tblmessage TABLE (
[value] nvarchar(max) NULL
)
as
begin
INSERT INTO #tblMessage
SELECT Tbl.Col.value('(code)[1]', 'nvarchar(max)') AS [value]
FROM #xmlData.nodes('/ul/li') Tbl(Col)
RETURN
end

using autocomplete with commas in a field

I'm trying to use autocomplete with a field with commas in it. When I type the comma it will ignore it, and won't return anything. So far I have this:
index.cfm
<!--- A simple form for auto suggest --->
<cfform action="autosuggest.cfm" method="post">
Artist:
<cfinput type="text" name="artist" size="50" autosuggest="cfc:autosuggest.findartist({cfautosuggestvalue})" autosuggestminlength="4" maxresultsdisplayed="5" /><br /><br />
</cfform>
autosuggest.cfc
<cfcomponent output="false">
<!--- Lookup used for auto suggest --->
<cffunction name="findartist" access="remote" returntype="string">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var local = {} />
<!--- Query Location Table --->
<cfquery name="local.query" datasource="#application.datasource#" >
select DISTINCT artist
from items
where artist like <cfqueryparam cfsqltype="cf_sql_varchar" value="#ucase(arguments.search)#%" />
order by artist
</cfquery>
<!--- And return it as a List --->
<cfreturn valueList(local.query.artist)>
</cffunction>
</cfcomponent>
When I try to search for example Brown,James it doesn't return anything. What do I need to put in it to return results with commas.
Thanks
One option is to have your function return an array, instead of a string. Then delimiters are not an issue.
<cffunction name="findartist" access="remote" returntype="array">
...
<cfreturn listToArray(valueList(local.query.artist, chr(30)), chr(30))>
</cffunction>
Update:
As Raymond pointed out, the only sure-fire way to avoid delimiter issues on the CF side is not to use them. Instead loop through the query to build the array, ie:
<cffunction name="findartist" access="remote" returntype="array">
...
<cfset local.arr = []>
<cfloop query="local.query">
<cfset arrayAppend(local.arr, local.query.artist)>
</cfloop>
<cfreturn local.arr>
</cffunction>

ColdFusion autosuggest in text field is not responsive

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})"

ColdFusion: Common Update Pattern

I usually create update statements like this. But I know there is a better way. How can I approve upon this? *Note the sample below is pseudo demo, may not run.
<cffunction name="updateEmp" returntype="void">
<cfargument name="empId" required="yes" hint="empId">
<cfargument name="firstName" required="yes" hint="firstName">
<cfargument name="lastName" required="yes" hint="lastName">
<!--- Get emp details in db --->
<cfquery datasource="#ds#" name="getEmployee">
SELECT *
FROM Employee
WHERE emp_id = <cfqueryparam
value="#arguments.empId#"
CFSQLType="CF_SQL_INTEGER">
</cfquery>
<!--- If employee is in db or if emp db details are different --->
<cfif getEmployee.recordCount eq 1
and getEmployee.firstName neq trim(arguments.firstName)
or getEmployee.lastName neq trim(arguments.lastName)>
<cfquery name="UpdateExistingEmployee" datasource="#ds#">
UPDATE Employee
SET 1 = 1
<cfif getEmployee.firstName neq trim(arguments.firstName)>
,firstName = <cfqueryparam
value="#arguments.firstName#"
CFSQLType="CF_SQL_VARCHAR" >
</cfif>
<cfif getEmployee.lastName neq trim(arguments.lastName)>
,lastName = <cfqueryparam
value="#arguments.lastName#"
CFSQLType="CF_SQL_VARCHAR" >
</cfif>
WHERE emp_id=<cfqueryparam
value="#emp_id#"
CFSQLType="CF_SQL_INTEGER">
</cfquery>
</cfif>
<!--- maybe return success? --->
</cffunction>
Edited:
<cffunction name="updateEmp" returntype="void">
<cfargument name="empId" required="yes" hint="empId">
<cfargument name="firstName" required="yes" hint="firstName">
<cfargument name="lastName" required="yes" hint="lastName">
<cfquery name="UpdateExistingEmployee" datasource="#ds#">
UPDATE Employee
SET firstName = <cfqueryparam
value="#arguments.firstName#"
CFSQLType="CF_SQL_VARCHAR" >
,lastName = <cfqueryparam
value="#arguments.lastName#"
CFSQLType="CF_SQL_VARCHAR" >
WHERE emp_id=<cfqueryparam
value="#emp_id#"
CFSQLType="CF_SQL_INTEGER">
</cfquery>
<!--- maybe return success? --->
</cffunction>
Not sure what you are trying to improve. If you just want to write less code you might just do an update:
<cffunction name="updateEmp" returntype="void">
<cfargument name="empId" required="yes" hint="empId">
<cfargument name="firstName" required="yes" hint="firstName">
<cfargument name="lastName" required="yes" hint="lastName">
<cfquery name="UpdateExistingEmployee" datasource="#ds#">
UPDATE Employee
SET firstName = <cfqueryparam value="#arguments.firstName#" CFSQLType="CF_SQL_VARCHAR">
,lastName = <cfqueryparam value="#arguments.lastName#" CFSQLType="CF_SQL_VARCHAR" >
WHERE emp_id=<cfqueryparam value="#emp_id#" CFSQLType="CF_SQL_INTEGER">
</cfquery>
</cffunction>
The check for an existing record is pretty much superfluous since the where clause will prevent any action if no emp_id matches, and why bother checking if the names match? If they do, then you just updated them to be the same, if they don't you're going to update them anyway. There's no logical reason to be doing all that checking.
Maybe check out Coldfusion ORM? Or, for something that would require less drastic changes to your codebase, you could use DataMgr (which really helps cut down on CRUD): http://datamgr.riaforge.org/