2013-02-25 15 views
5

Ich versuche AngularJS mit einem ColdFusion-Backend aufzunehmen und stoße auf einige Hindernisse. Ich ändere ihre "To Do" App http://angularjs.org/ mit der CF Art Gallery Datenbank. Ich versuche, einen ColdFusion CFC über AJAX mit einer Angular-App zu verknüpfen.AngularJS und ColdFusion CFCs

Unten ist mein 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> 

Ich nenne die CFC AngularJS mit dem folgenden Code:

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

Ich weiß, dass ich eine Antwort bekommen. Unten ist die JSON-String Chrome-Entwickler-Tools für mich Returns:

{ 
"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"] 
]} 

Das ist nicht wie die Notation in ihrer Demo verwendet Angular sieht:

[ 
{text:'learn angular', done:true}, 
{text:'build an angular app', done:false} 
] 

jemand mich in die richtige Richtung zeigen kann, wie auf Wie kann ich dafür sorgen, dass dies richtig funktioniert? Idealerweise möchte ich den CFC intakt lassen, damit er für eine andere Anwendung wiederverwendet werden kann, so dass die JSON-Manipulation im Javascript-Ende erfolgen müsste.

+0

Was genau ist Ihre Frage? Übrigens verweist Ihr Erfolgsrückruf nicht korrekt auf Antwortdaten. Es sollte 'function (response) {$ scope.todos = response.data.DATA; } '. – Stewie

+0

Ausdrücklich gesagt, meine Frage wäre "Wie ersetze ich die Informationen aus AngularJS TODO Tutorial mit einem von der artist.cfc? Ich habe versucht, die Funktion (Antwort) {$ scope.todos = response.data.DATA;} 'und ich bekomme einen' TypeError: Kann die Eigenschaft 'DATA' von 'undefined' nicht lesen – Chester

+0

Mein Fehler, ich habe die explizite 'promise.success' Methode (die den Callback mit Daten und Status Parametern füttert) mit' promise.then 'verwechselt Methode, die die Callbacks mit dem Antwortobjekt füttert, das eine Dateneigenschaft hat, aber in diesem Fall sollte Ihr Callback 'function (data) {$ scope.todos = data.DATA;}' sein, da Ihre tatsächliche Ajax-Antwort gegeben ist body gibt wirklich den JSON zurück, den Sie in Ihrer Antwort gepostet haben. – Stewie

Antwort

5

Standardmäßig verwendet Coldfusion eine andere JSON-Notation als Sie möglicherweise gewohnt sind. Die Spaltennamen werden in einem Array gespeichert, während die Daten in einem anderen gespeichert werden. Die von uns implementierte Lösung beinhaltete die Änderung der CFquery in ein Array. Dann JSONEnoding dieses Array.

Sie diese Funktion hier brauchen:

<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> 

Und dann wird Ihre Rückkehr wie folgt aussehen:

<cfreturn SerializeJson(QueryToArray(getArtists_SQL),true)> 

Die Sache, sich daran zu erinnern ist, dass ein CFQUERY Objekt andere Eigenschaften wie Record enthält .. .und höchstwahrscheinlich will das JS nur die Daten. Ich weiß nicht, ob es eine elegantere Lösung dafür gibt, aber das ist die Lösung, auf die wir stießen, als wir ein ähnliches Problem mit JQgrid hatten.

+0

Nun, das hat die JSON-Antwort vom CFC auf '{" ROWCOUNT "geändert: 15," COLUMNS ": [" TEXT "," DONE "]," DATA ": {" TEXT ": [" Aiden "," Austin Elicia, Jeff, Lori, Maxwell, Paul, Raquel, Viata, Diane, Anthony, Ellery , "Mike", "DONE": ["Donolan", "Weber", "Kim", "Baclawski", "Johnson", "Wilson", "Trani", "Young", "Trenton", "Demo" "Kunovic", "Buntel", "Bunte", "Frazier", "Nimer"}}}, aber es ist immer noch nicht so, wie das Tutorial die Daten hatte. – Chester

+0

@Chester Zu richtig bist du. Entschuldigen Sie. Ich werde meine Antwort aktualisieren. –

+0

Nachdem ich darüber nachgedacht habe, bin ich auch zu dem gleichen Schluss gekommen, wenn auch auf andere Weise. Ich wollte den CFC wirklich frei von jeglichen JSON-Modifikationen halten, so dass der CFC wiederverwendet werden kann, aber ich dachte mir, dass es einfacher ist, irgendwelche CFCs in der Zukunft zu ändern/hinzuzufügen, als das Javascript zu machen. Davon abgesehen habe ich https://github.com/iknowkungfoo/ArrayCollection verwendet und die gesamte Abfrage so umgebrochen, wie es sein sollte. Danke für Ihre Hilfe. Jetzt muss ich herausfinden, wie die Antwort aus meiner Sicht wieder angezeigt wird. – Chester

1

Um mit der obigen Antwort von Blaise zu gehen. Das QueryToArray, das ich verwende, betrachtet die Spaltenliste des Query-Objekts. Dies ist so der Fall der Spalte Aliase bleibt erhalten. Sonst wird es alle Kappen in Ihrem JSON sein

/**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); 
}