2011-09-27 15 views
6

構造体を返すリモートCFCがあります。 cfajaxproxyを使用して呼び出されます。私は、JSONオブジェクトをJSONオブジェクトの最初の構造体に配置する必要があります。しかし、返されるJSONは混在しています。リモートCFC関数から返されたJSONが異常です

ここにリモート機能があります。

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

これはフォームページの上部に設定したcfajaxproxyです。

私のフォームのonSubmitハンドラでリモート関数に対して行われた呼び出しです。

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

投稿リクエストの関数に送信されるデータ(上記の変数)は次のとおりです。

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

ここでは、関数から返されたJSON応答を示します。

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

私は、応答は次のようになり構造が作成されたのと同じ順序であることにしたいです。

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

このようにして、応答を繰り返すと、エラーがある最初のフォームフィールドにフォーカスを設定できます。

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

これは、プロジェクトのフィールドではなく、フォームの説明の2番目のフィールドにフォーカスを置きます。

+0

可能な複製http://stackoverflow.com/questions/4515676/keep-the-order-of-the-json-keys-during-json-conversion-to-csv –

答えて

7

ColdFusion構造体のキーは決して特定の順序で格納されません。ただし、特定の順序でキーを格納および取得するJava LinkedHashMap(CF Structの下にあるjava)を作成する方法を示すfound one postがあります。

<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:ダンのソリューション(代わりに構造体の配列)は、おそらくずっと容易になるだろう。

+0

私はajax呼び出しを介してリモート検証機能を使用していただけで、おそらくダンのアプローチに行き詰まってしまい、配列にエラーが返されました。しかし、JSが無効になっている場合に備えて、サーバー上の関数を呼び出します。配列ではなく構造体のエラーを返すことは、エラー表示コードでうまく動作します。 LinkedHashMapを使用すると問題は解決しました。返されたJSONはアイテムが追加されたのと同じ順番でした。 – Brandon

5

戻される文字列を手動で作成しない限り、返されるJSON構造データの順序を(簡単に)制御することはできません。オーダーに頼らなければならない場合は、構造体ではなく配列でエラーを返す必要があります。エラー構造の配列を返すこともでき、CFは正しい配列順序を維持します。

私はそうのようなあなたのデータを返します:

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

これはあなたの代わりに自分のエラーと同時にあなたのベースmessageareErrorsキーを扱う、オーバーループへのエラーの別々の配列を与えるだろう。それらを別々のエンティティに分割して、クライアント側でループするのが簡単になります。

+0

これは正しいアプローチのように聞こえます。私はそれを試してみる。 – Brandon

+0

あなたが突っ込んだことがあれば教えてください。私は答えに直接コードを入力し、それを実際にテストして実行しませんでした。しかし、すべてが良いものになるはずです。 –

+0

あなたのコードで見つけた1つの問題があります。 tempError構造体は配列に1回だけ追加され、最後のエラーだけがエラー配列に表示されるように上書きされ続けます。各cfifブロック内のtempError = StructNew()を移動すると、これが修正されます。 – Brandon

3

structはCFMLで順序付けされていません(これは単なるHashmapのようなコレクションです)。

あなたが注文した構造体をしたい場合は、代わりに構造体の配列を使用するために滞在するために何かをしたい場合は、

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

に最も簡単な方法を使用します。