Pull Down with binding and AJAX

孤街浪徒 提交于 2020-01-11 09:49:08

问题


I am new to ColdFusion and just started learning about Ajax. The question I have is that I found on the web some cool coding to implement two pull down menus, where is the second one is dependent on what is selected from the first. The goal though is to pull all the values in the pull down list from a select query.

I am using the binding feature, which I just learned about. Everything in the first pull down is pulling correctly. The problem though is the second one. The error I am getting from AJAX logger is "Error invoking: Error Executing Database Query" Any advice would be greatly appreciated. Also thank you in advance for your help.

select.cfc

<cfcomponent output="false">

    <!--- 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 CAT_DESC
            FROM   service_table
            ORDER BY CAT_DESC
        </cfquery>

        <!--- Convert results to array---> 
        <cfloop index="i" from="1" to="#getServiceCat.recordcount#">
            <cfset result[i][1]=getServiceCat.CAT_DESC[i]>
            <cfset result[i][2]=getServiceCat.CAT_DESC[i]>
        </cfloop>

        <!--- And return it --->
        <cfreturn result>
    </cffunction>

    <!--- Get Service Type by Cat description type --->
    <cffunction name="getServiceType2" access="remote" returnType="array">
        <cfargument name="CAT_DESC" type="string" required="true">

        <!--- Define variables --->
        <cfset var data="">
        <cfset var result=ArrayNew(2)>
        <cfset var i=0>

        <!--- Get data --->
        <cfquery name="getServiceType2" datasource="SOME_DATABASE" dbtype="query">
            SELECT DISTINCT com_service_code, report_desc
            FROM   service_table
            WHERE  CAT_DESC = #ARGUMENTS.CAT_DESC# 
            ORDER BY report_desc
        </cfquery>
        </cfif>

        <!--- Convert results to array --->
        <cfloop index="i" from="1" to="#getServiceType2.recordcount#">
            <cfset result[i][1]=getServiceType2.com_service_code[i]>
            <cfset result[i][2]=getServiceType2.report_desc[i]>
        </cfloop>

        <!--- And return it --->
        <cfreturn result>
    </cffunction>

 </cfcomponent>

The above is the cfc which handles all the queries. One of the main reason for this solution is the simplicity of the code that is required within the form.

 ...
 <td>Select Category: <cfselect name="catdesc"
                                 bind="cfc:select.cat_description()"
                                 bindonload="true"/><br />
 </td>
 ...
 <td>Select Service:  <cfselect name="service"
                                bind="cfc:select.getServiceType2({catdesc})"
                                bindonload="false"/>
 </td>

I have searched for almost 2 days trying to find a solution to the query error. I know that the query works in SQL so I believe the issue has to do with AJAX and not correctly implementing the WHERE clause for the second pull down.

Again any advice or suggestions would be great. Additionally if you would do this solution another way I am more than happy to try that as well. As I stated I am very new to this language. Only 2 weeks in.


回答1:


Testing CFC's

Always test cfc's in CF before plugging them into ajax. There is no point messing with bindings until after you have verified the cfc works without error, because if it does not work in CF, it is not going work with ajax either. The only difference is the errors will be harder to find.

As others suggested, start small. Test the query by itself. Then move onto to testing the CFC either using <cfinvoke> or simply invoke it from your browser with test values like:

http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc= 
http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc=someValue

Error

In regards to the error, we need to see the full error message to provide more specific advice. However, looking at the query/code some likely causes are:

  1. CAT_DESC is a varchar column, in which case your argument must be enclosed in single quotes. Otherwise the database will think the argument value is an object name (table or column).

    WHERE CAT_DESC = '#ARGUMENTS.CAT_DESC#' 
    
  2. .. OR CAT_DESC is a numeric column, but your argument is empty. That would result in an invalid sql statement. You need to ensure a valid number is passed into the query (Or you could skip the WHERE clause when the argument is empty, depending on the desired results). One common approach is using the val() function to convert empty strings and other non-numeric values to zero, ie:

    WHERE CAT_DESC = #val(ARGUMENTS.CAT_DESC)#

  3. It also looks like you have a stray </cfif> after the second query. (Assuming it is not a copy/paste error)

  4. One other thing, your second query specifies both datasource and dbtype. Those two attributes are mutually exclusive. Having both may cause a syntax error (I have not tried it). Either way you should only use one of them (most likely datasource).

SQL Injection

That said - the query above is vulnerable to sql injection. You should always use <cfqueryparam> on all variable query parameters to guard against sql injection. It has other benefits as well (performance, data type checking, etcetera). But sql injection protection is the most critical in a web application.

<!--- substitute the correct type for your db column --->
WHERE CAT_DESC = <cfqueryparam value="#ARGUMENTS.CAT_DESC#" 
                         cfsqltype="cf_sql_varchar">

Improvements

As of CF8.0.1+, cfselect can bind to a query object (not just an array). So instead of building an array, simply return the raw query from the function.

    <cffunction name="getServiceType2" access="remote" returnType="query">
        <cfargument name="CAT_DESC" ....>

        <cfset var data="">

        <cfquery name="data" ..> 
           SELECT TheQueryColumnToDisplay, TheQueryColumnUsedForListValue
           FROM  ... 
           WHERE ... 
        </cfquery>

       <cfreturn data>
    </cffunction>

Then specify which column(s) to use for the display and value attributes:

    <cfselect name="service" 
              bind="cfc:select.getServiceType2({catdesc})"
              display="TheQueryColumnToDisplay"
              value="TheQueryColumnUsedForListValue" ...>



回答2:


My suggestion is to do one thing at a time. For your specific situation,

First, get your query to work with a cfquery tag.

Second, get it to work inside a function where you pass an argument to the function.

Next, put the function inside a cfc and call it from a cfc page using either or by creating an object and calling the function.

Finally do the bind.

This approach will make the errors more visible so that you can do something about them.

Other observations

  1. use query parameters.
  2. try to pass an id field to your query instead of a text description


来源:https://stackoverflow.com/questions/14527652/pull-down-with-binding-and-ajax

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!