问题
I'm stumped. I have an existing autocomplete function which worked when called from a ColdFusion autosuggest input. Now, I'm trying to convert the page to use a jQuery autocomplete input, and can't make it work. Here's the existing function, in autosuggest.cfc:
<cffunction name="lookupSerialNumber" 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">
SELECT DISTINCT SERIAL_NUMBER
FROM myTable
WHERE SERIAL_NUMBER LIKE '%#trim(ARGUMENTS.search)#%'
ORDER BY SERIAL_NUMBER
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset ArrayAppend(result, list)>
</cfloop>
<!--- And return it --->
<cfreturn result />
</cffunction>
When I call it from my autocomplete input after entering "01", the Console shows a response like this:
["0000003001","0100002000","0100002001","0100002002","0100002003","0100002004",7300000100,7300000101,7300000102,7300000103,7300000104,7300000105,7300000107,7300000108,7300000109,7300000110,7300000111,7300000112]
Note that the first six responses are inside double quotes, while the rest are not. The autocomplete shows the first six responses, but not the rest.
So that's my first problem. The second is that I want the response to be injected into both the text and the value of the input; currently, only the text shows the response. I'm not surprised, as I'm only returning a single value. However, I can't figure out how to accomplish this.
I've tried initializing the autocomplete with a parse function, like so:
$(document).ready(function(){
$('#myInputID').autocomplete(
{source: function(request, response) {
$.ajax({
url: "cfc/autoSuggest.cfc?method=lookupSerialNumber>&returnformat=json",
dataType: "json",
data: {
search: request.term,
maxRows: 10
},
success: function(data) {
response(data);
}
})
},
parse: function(data){
return $.map(data, function(item) {
return { data: item, value: item, result: item };
});
}
});
});
but this accomplishes nothing. Since the parse function isn't in the autocomplete API, I'm flying blind here.
I figured that these problems were related enough to not split them out into two questions; let me know if you think I should. As always, thanks.
回答1:
Put your query results in a structure and add that to an array. Then convert to json. The autocomplete is expecting json back and either a label
or a value
field or both. Here is an example:
<cffunction name="lookupSerialNumber" access="remote" returntype="String" >
<cfargument name="search" type="any" default="">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(1)>
<cfset var returnStruct = "">
<!--- Do search --->
<cfquery name="data">
SELECT DISTINCT SERIAL_NUMBER
FROM myTable
WHERE SERIAL_NUMBER LIKE <cfqueryparam value="%#trim(ARGUMENTS.search)#%"
cfsqltype="cf_sql_varchar">
ORDER BY SERIAL_NUMBER
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset returnStruct = StructNew() />
<cfset returnStruct["label"] = SERIAL_NUMBER />
<cfset ArrayAppend(result,returnStruct) />
</cfloop>
<!--- And return it --->
<cfreturn serializeJSON(result) />
</cffunction>
You can use the serializeJSON
function if it's available in whatever version of CF you are using. If not, build the json string by hand.
Here is a tut: http://www.jensbits.com/2010/03/18/jquery-ui-autocomplete-with-coldfusion/
回答2:
Just came across this looking for a similar solution, but I must say, returning the array of structs doesn't follow most conventions for JSON AJAX returns, even after using serializeJSON.
The other answer returns something like
[{key:value}, {key:value}, {key:value}...]
whereas typically, you want to see
{key:value,key:value,key:value...}
So here is my adjusted version of the code for those who need to work with the latter format
<cffunction name="lookupSerialNumber" access="remote" returntype="String" >
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<cfset var result=StructNew()> <!--- Is now a Struct instead of Array --->
<!--- Do search --->
<cfquery name="data">
SELECT DISTINCT SERIAL_NUMBER
FROM myTable
WHERE SERIAL_NUMBER LIKE '%#trim(ARGUMENTS.search)#%'
ORDER BY SERIAL_NUMBER
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset returnStruct = StructNew() />
<cfset returnStruct["label"] = SERIAL_NUMBER />
<cfset StructAppend(result,returnStruct) />
<!--- Append the temporary struct to the main struct --->
</cfloop>
<!--- And return it --->
<cfreturn serializeJSON(result) />
The advantage to this is easier parsing:
$.ajax({
url: 'path/to.cfc',
dataType: 'json',
data: {
search: searchWord
}
success: function(data) {
//Easy Parsing Bit here...
$.each(data, function(key, val) {
alert(key + ': ' + val);
})
}
})
Whereas before, you'd have to enter the array THEN parse the individual JSON entries...
回答3:
CFRemoting in OO Fashion Using Mura CMS Here ...
snProxy.cfc
<cfcomponent extends="mura.cfobject">
<cfset variables.searchterm = ''>
<cffunction name="get" access="remote" output="true">
<cfargument name="searchterm" required="true">
<cfset var $=getBean("MuraScope").init(session.siteid)>
<cfset variables.searchterm = arguments.searchterm >
<cfquery name="get" datasource="#request.dsn#">
SELECT DISTINCT SERIAL_NUMBER
FROM tbl_serial_numbers
WHERE SERIAL_NUMBER like <cfqueryparam value="%#variables.searchterm#%" cfsqltype="cf_sql_varchar" />
</cfquery>
<cfset response = listToArray(valueList(get.SERIAL_NUMBER))>
<cfset data = #createobject("component","mura.json").encode(response)#>
<cfreturn data />
</cffunction>
</cfcomponent>
JQuery Bind ...
<script type="text/javascript">
$(function() {
$("input##serial_numbers").autocomplete({
source: "/com/snProxy.cfc?method=get&returnFormat=json",
minLength: 1
});
});
</script>
来源:https://stackoverflow.com/questions/7814575/forming-json-from-coldfusion-query-for-use-in-jquery-autocomplete