我正在尝试使用ColdFusion后端获取AngularJS,并遇到了几个障碍。我正在使用CF Art Gallery数据库修改他们的“待办事项”应用http://angularjs.org/。我正在尝试使用AJAX将ColdFusion CFC链接到Angular应用程序。
以下是我的artists.cfc:
<cfcomponent>
<cffunction name="getArtists" access="remote" >
<cfargument name="firstName" default="">
<cfargument name="lastName" default="">
<cfquery name="getArtists_sql" datasource="cfartgallery">
SELECT
firstname as text,
lastname as done
FROM artists
WHERE 0=0
<cfif firstName neq "">
AND ucase(firstname) like ucase('%#FIRSTNAME#%')
</cfif>
<cfif lastName neq "">
OR ucase(lastname) like ucase('%#LASTNAME#%')
</cfif>
</cfquery>
<cfreturn getArtists_sql>
</cffunction>
</cfcomponent>
我使用AngularJS使用以下代码调用CFC:
function TodoCtrl($scope, $http) {
$http.get('cfc/artists.cfc?method=getArtists&returnformat=json').
success(function (response) {
$scope.todos = data.DATA;
}).
error(function (data) {
$scope.todos = data;
});
}
我知道我得到了回复。以下是Chrome的开发者工具为我返回的JSON字符串:
{
"COLUMNS":
["TEXT","DONE"],
"DATA":[
["Aiden","Donolan"],
["Austin","Weber"],
["Elicia","Kim"],
["Jeff","Baclawski"],
["Lori","Johnson"],
["Maxwell","Wilson"],
["Paul","Trani"],
["Raquel","Young"],
["Viata","Trenton"],
["Diane","Demo"],
["Anthony","Kunovic"],
["Ellery","Buntel"],
["Emma","Buntel"],
["Taylor Webb","Frazier"],
["Mike","Nimer"]
]}
这看起来不像Angular在他们的演示中使用的符号:
[
{text:'learn angular', done:true},
{text:'build an angular app', done:false}
]
有人能指出我正确的方向,以便我能够让它正常工作吗?理想情况下,我希望保持CFC完好无损,以便可以在不同的应用程序中重用它,因此必须在Javascript端完成JSON操作。
答案 0 :(得分:7)
默认情况下,Coldfusion使用与您习惯的不同的JSON表示法。列名存储在一个数组中,而数据存储在另一个数组中。我们实现的解决方案涉及将CFquery更改为数组。然后JSONEncoding那个数组。
您将需要此功能:
<cffunction name="QueryToArray" access="public" returntype="array" output="false"hint="This turns a query into an array of structures.">
<cfargument name="Data" type="query" required="yes" />
<cfscript>
// Define the local scope.
var LOCAL = StructNew();
// Get the column names as an array.
LOCAL.Columns = ListToArray( ARGUMENTS.Data.ColumnList );
// Create an array that will hold the query equivalent.
LOCAL.QueryArray = ArrayNew( 1 );
// Loop over the query.
for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount ; LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
// Create a row structure.
LOCAL.Row = StructNew();
// Loop over the columns in this row.
for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen( LOCAL.Columns ) ; LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
// Get a reference to the query column.
LOCAL.ColumnName = LOCAL.Columns[ LOCAL.ColumnIndex ];
// Store the query cell value into the struct by key.
LOCAL.Row[ LOCAL.ColumnName ] = ARGUMENTS.Data[ LOCAL.ColumnName ][ LOCAL.RowIndex ];
}
// Add the structure to the query array.
ArrayAppend( LOCAL.QueryArray, LOCAL.Row );
}
// Return the array equivalent.
return( LOCAL.QueryArray );
</cfscript>
</cffunction>
然后你的回报将如下:
<cfreturn SerializeJson(QueryToArray(getArtists_SQL),true)>
要记住的是,CFquery对象包含其他属性,如recordcount ...而且很可能,JS只需要数据。我不知道是否有一个更优雅的解决方案,但这是我们遇到与JQgrid类似问题时的解决方案。
答案 1 :(得分:2)
赞同布莱斯的上述答案。 我使用的queryToArray查看查询对象的columnList。 这样就保留了列别名的情况。否则它将是你的JSON中的全部大写
/**queryToArray
* utility method to keep the code dry.
* @hint does exactly what the name says, take a query, makes it an array of stucts
* @hint columnLabels pass in a list of columnLabels to just return those columns
*/
public array function queryToArray(required query data, any columnLabels=false){
var columns = listToArray(arguments.data.columnList);
if(arguments.columnLabels != false){
columns = listToArray(arguments.columnLabels);
}
var queryArray = arrayNew(1);
for(i=1; i <= arguments.data.RecordCount; i++){
row = StructNew();
for (j=1; j <= ArrayLen(columns); j++){
columnName = columns[j];
row[columnName] = arguments.data[columnName][i];
}
arrayAppend(queryArray, row);
}
return(queryArray);
}
答案 2 :(得分:2)
或者您可以在javascript中使用此辅助函数将查询作为(常见)键值对象数组。
function CFQueryParser(data) {
let items = [];
Object.keys(data.DATA).forEach((i) => {
let item = {};
Object.keys(data.COLUMNS).forEach((j) => {
item[data.COLUMNS[j]] = data.DATA[i][j];
});
items.push(item);
})
return items;
}