2013-02-25 12 views
5

Próbuję podnieść AngularJS z powrotem do ColdFusion i uruchamiam kilka blokad dróg. Modyfikuję ich aplikację "Do zrobienia" http://angularjs.org/ za pomocą bazy danych galerii sztuki CF. Próbuję połączyć CFC ColdFusion z aplikacją Angular, używając AJAX.CFC AngularJS i ColdFusion

Poniżej jest moje 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> 

nazywam CFC za pomocą angularjs z następującego kodu:

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

wiem, że dostanę odpowiedź z powrotem. Poniżej narzędzia programistyczne na ciąg JSON Chrome wraca do mnie:

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

To nie wygląda jak notacji Kątowymi stosowanych w ich demo:

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

Czy ktoś może wskazać mi w dobrym kierunku, aby jak mogę zrobić, żeby to działało poprawnie? Idealnie, chciałbym zachować nienaruszoną CFC, aby można ją było ponownie wykorzystać dla innej aplikacji, więc manipulacja JSON musiałaby zostać wykonana na końcu Javascript.

+0

Czym dokładnie jest twoje pytanie? BTW, twój oddzwonienie sukcesu nie odwołuje się poprawnie do danych odpowiedzi. Powinien to być 'function (response) {$ scope.todos = response.data.DATA; } '. – Stewie

+0

Jednoznacznie, moje pytanie brzmiałoby: "Jak zastąpić informacje z samouczka TODO AngularJS jednym z artist.cfc? Próbowałem funkcji (response) {$ scope.todos = response.data.DATA;} 'i otrzymuję' TypeError: Can not read property 'DATA' of undefined' – Chester

+0

My bad, Myliłem jawną metodę "obietnica.success" (która podaje callback z danymi i parametrami statusu) z 'promise.then' metoda, która podaje callback (y) za pomocą obiektu odpowiedzi, który ma właściwość data, ale w takim przypadku callback powinien być 'function (data) {$ scope.todos = data.DATA;}' biorąc pod uwagę faktyczną odpowiedź ajax body naprawdę zwraca JSON, który umieściłeś w swojej odpowiedzi. – Stewie

Odpowiedz

5

Domyślnie Coldfusion używa innej notacji JSON, niż może być używana. Nazwy kolumn są przechowywane w jednej tablicy, podczas gdy dane są przechowywane w innej. Zaimplementowane rozwiązanie wymagało zmiany CFquery na tablicę. Następnie JSONEnkodując tę ​​tablicę.

Będziesz potrzebował tej funkcji tutaj:

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

I wtedy Twój zysk będzie wyglądać następująco:

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

Rzeczą do zapamiętania jest to, że obiekt CFquery zawiera inne właściwości, takie jak RecordCount .. i najprawdopodobniej JS chce tylko danych. Nie wiem, czy istnieje bardziej eleganckie rozwiązanie tego problemu, ale jest to rozwiązanie, na które trafiliśmy, gdy mieliśmy podobny problem z JQgrid.

+0

To zmieniło odpowiedź JSON z CFC na '{" ROWCOUNT ": 15," COLUMNS ": [" TEXT "," DONE "]," DATA ": {" TEXT ": [" Aiden "," Austin "," Elicia "," Jeff "," Lori "," Maxwell "," Paul "," Raquel "," Viata "," Diane "," Anthony "," Ellery "," Emma "," Taylor Webb " , "Mike"], "DONE": ["Donolan", "Weber", "Kim", "Baclawski", "Johnson", "Wilson", "Trani", "Young", "Trenton", "Demo" , "Kunovic", "Buntel", "Buntel", "Frazier", "Nimer"]}}}, ale nadal nie jest tak, jak samouczek miał dane. – Chester

+0

@Chester Zbyt dobrze, prawda. Przepraszam. Zaktualizuję moją odpowiedź. –

+0

Po przemyśleniu tego, doszedłem do tego samego wniosku, choć w inny sposób. Naprawdę chciałem, aby CFC była czysta z wszelkich modyfikacji JSON, aby CFC mogło być ponownie użyte, ale pomyślałem, że łatwiej będzie zmodyfikować/dodać jakiekolwiek CFC w przyszłości, niż to, że zrobię javascript. Biorąc to pod uwagę, użyłem https://github.com/iknowkungfoo/ArrayCollection i zapakowałem całe zapytanie do tego, co powinno być. Dzięki za pomoc. Teraz muszę wymyślić, jak odzyskać odpowiedź do wyświetlenia w moim widoku. – Chester

1

Aby przejść do powyższej odpowiedzi od Blaise. Używając queryToArray używam parametrów columnList obiektu zapytania. Tak jest w przypadku aliasów kolumnowych. W przeciwnym razie będą to wszystkie ograniczenia w twoim 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); 
}