2011-09-27 8 views
6

Mam zdalny CFC, który zwraca strukturę. Nazywa się to za pomocą cfajaxproxy. Chcę, aby JSON wrócił do porządku, tj. Najpierw do struktury najpierw do obiektu JSON. Jednak zwracany JSON jest w mieszanej kolejności.JSON wrócił ze zdalnej funkcji CFC jest nieczynny

Oto funkcja zdalna.

<cfcomponent displayname="validation" hint=""> 
    <cffunction name="validateForm" displayname="validateForm" hint="" access="remote" verifyClient="yes" returntype="struct"> 

     <cfargument name="formVals" type="struct" required="yes"> 

     <cfset errors = StructNew()> 

     <cfif formVals.project neq "project"> 
       <cfset errors["project"] = "Invalid project name." /> 
     </cfif> 

     <cfif Len(formVals.description) eq 0> 
      <cfset errors["description"] = "Please enter a description." /> 
     </cfif> 

     <cfif StructIsEmpty(errors)> 
      <cfset errors["message"]["type"] = "success"> 
      <cfset errors["message"]["text"] = "Client and server-side validation passed successfully."> 
      <cfset errors["areErrors"] = false> 
     <cfelse> 
      <cfset errors["message"]["type"] = "validation"> 
      <cfset errors["message"]["text"] = "Please fix the errors, and resubmit."> 
      <cfset errors["areErrors"] = true> 
     </cfif> 

     <cfreturn errors /> 

    </cffunction> 
</cfcomponent> 

To jest cfajaxproxy, który ustawiłem u góry strony mojego formularza.

<cfajaxproxy cfc="validation" jsclassname="validation"> 

Oto wywołanie funkcji zdalnej w module obsługi onSubmit w moim formularzu.

var v = new validation(); 
v.setHTTPMethod("POST"); 
var errors = v.validateForm(o); 

Oto dane (o zmienna powyżej), które są wysyłane do funkcji we wniosku o wpis.

{"formVals":{"project":"","description":""}} 

Oto odpowiedź JSON zwrócona z funkcji.

{"message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"description":"Please enter a description.","project":"Invalid project name.","areErrors":true} 

Chcę, aby odpowiedź była w tej samej kolejności, w jakiej została utworzona struktura, która wyglądałaby tak.

{"project":"Invalid project name.","description":"Please enter a description.","message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"areErrors":true} 

W ten sposób, gdy sprawdzam odpowiedź, mogę ustawić fokus na pole pierwszego formularza z błędem.

var focusSet = false; 

$.each(errors, function(key, val){ 
    //alert(key + ': ' + val); 
    if(key != 'message' && key != 'areErrors') { 
     var fi = $('#' + key).parents('.formItem').filter(':first'); 
     fi.addClass("inError"); 
     fi.find('.err').filter(':first').html(val); 
     if(!focusSet) { 
      $('#' + key).focus(); 
      focusSet = true; 
     } 
    } 
}); 

Teraz koncentruje się w drugim polu formularza, opisie, zamiast w polu projektu.

+0

Prawdopodobny duplikat http://stackoverflow.com/questions/4515676/keep-the-order-the-json-keys-during-json-conversion-to-csv –

Odpowiedz

7

Klucze struktury ColdFusion nigdy nie są przechowywane w żadnej określonej kolejności. Jednak I found one post pokazuje, w jaki sposób można utworzyć java LinkedHashMap (która jest java pod CF Struct) do przechowywania i pobierania kluczy w określonej kolejności.

<cfset pets = CreateObject("java", "java.util.LinkedHashMap").init()> 
<cfscript> 
pets["Cat Name"] = "Leo"; 
pets["Dog Name"] = "Meatball"; 
pets["Fish Name"] = "Lil Fish"; 
pets["Bird Name"] = "PePe"; 
pets["Snake Name"] = "Sizzle"; 
</cfscript> 
<cfloop collection="#pets#" item="key" > 
    <cfoutput> 
    #key#: #pets[key]#<br/> 
    </cfoutput> 
</cfloop>

EDIT: rozwiązanie Dana (array zamiast struct) prawdopodobnie będzie znacznie łatwiejsze.

+0

Gdybym tylko korzystał z funkcji zdalnego sprawdzania przez wywołania ajax, prawdopodobnie poszedłbym z podejściem Dana i zwrócił błędy w tablicy. Jednak wywołuję też funkcję na serwerze, na wypadek gdyby JS był wyłączony. Zwracanie błędów w strukturze, a nie w tablicy działa lepiej z moim kodem wyświetlania błędu. Korzystanie z LinkedHashMap rozwiązało problem; zwrócony JSON był w tej samej kolejności, w której dodano elementy. – Brandon

5

Nie można (łatwo) kontrolować kolejności zwróconych danych struktury JSON, chyba że ręcznie skonstruowano ciąg znaków, aby zwrócić te dane. Jeśli musisz polegać na zamówieniu, musisz zwrócić błędy w tablicy zamiast w strukturze. Możesz nawet zwrócić tablicę struktur błędów, a CF zachowa prawidłową kolejność tablic.

wrócę danych tak:

<cfcomponent displayname="validation" hint=""> 
    <cffunction name="validateForm" displayname="validateForm" hint="" access="remote" verifyClient="yes" returntype="struct"> 

     <cfargument name="formVals" type="struct" required="yes"> 

     <cfset var retVal = StructNew() /> 
     <cfset var tempError = StructNew() /> 
     <cfset retVal.errors = ArrayNew(1) /> 

     <cfif formVals.project neq "project"> 
      <cfset tempError["key"] = "project" /> 
      <cfset tempError["message"] = "Invalid project name." /> 
      <cfset ArrayAppend(retVal.errors, Duplicate(tempError)) /> 
     </cfif> 

     <cfif Len(formVals.description) eq 0> 
      <cfset tempError["key"] = "description" /> 
      <cfset tempError["message"] = "Please enter a description." /> 
      <cfset ArrayAppend(retVal.errors, Duplicate(tempError)) /> 
     </cfif> 

     <cfif ArrayIsEmpty(retVal.Errors)> 
      <cfset retVal["message"]["type"] = "success" /> 
      <cfset retVal["message"]["text"] = "Client and server-side validation passed successfully."> 
      <cfset retVal["areErrors"] = false> 
     <cfelse> 
      <cfset retVal["message"]["type"] = "validation"> 
      <cfset retVal["message"]["text"] = "Please fix the errors, and resubmit."> 
      <cfset retVal["areErrors"] = true> 
     </cfif> 

     <cfreturn retVal /> 

    </cffunction> 
</cfcomponent> 

To daje osobną tablicę błędów pętli nad, zamiast czynienia z bazy message i areErrors klawiszy w tym samym czasie, co swoimi błędami. Podziel je na osobną całość, a będziesz mieć łatwiejszy czas na zapętlenie ich po stronie klienta.

+0

To brzmi jak prawidłowe podejście. Wypróbuję to. – Brandon

+0

Daj mi znać, jeśli trafisz na jakiekolwiek przeszkody. Wpisałem kod bezpośrednio w odpowiedzi i nie uruchomiłem go, aby go przetestować. Jednak wszystko powinno być dobre. –

+0

Jest jeden problem, który znalazłem w twoim kodzie. Struktura tempError zostaje dodana do tablicy tylko raz i ciągle jest nadpisywana, tak że tylko ostatni błąd pojawia się w tablicy błędów. Przenoszenie tempError = StructNew() wewnątrz każdego bloku cfif naprawia to. – Brandon

3

struct nie jest uporządkowany w CFML (jest to po prostu kolekcja podobna do Hashmap).

Jeśli chcesz zamawiać struct, użyj

struct function orderedStructNew() 
{ 
    return createObject("java","java.util.LinkedHashMap").init(); 
} 
2

Najprostszym sposobem, jeśli chcesz coś zatrzymać się w celu korzystania z tablicy zamiast struktury.

Powiązane problemy