1

データベースに値を挿入するためにCFGRIDandを使用しています。CFGRIDUPDATE問題は、各レコードがグリッドにない追加のフィールドを取得する必要があることです。その追加のフィールドをレコードに保存する方法はありますか、または CFGRID の代替手段を作成する必要がありますか?

基本的に、グリッドに入力しているユーザーがたくさんいます。ページはカテゴリ ID を取得しています。すべてのユーザーをそのカテゴリ ID で保存したい。

もう 1 つの方法は、作成したばかりのレコードを含むすべての主キーのリストを取得し、それらすべてをカテゴリ ID で更新できる場合です。しかし、CFGRIDUPDATE作成された行に関する情報は返されないようです。

4

2 に答える 2

3

-- 元の回答が削除されました --

私の元の回答に対するあなたのコメントに基づいて、Category_ID はおそらく結合テーブル上の外部キーであり、(何らかの理由で) 最初の表示クエリに含めることができない、または単に望んでいるという暗黙の仮定があります。ユーザーが介入することなく、インライン挿入中に含まれる動的変数をグリッドに含める (つまり、ユーザーが Category_ID 自体を選択することを物理的に防止しますが、供給されることによって、ある程度の容量では動的になります)。 URL 変数から)。

正しければ、本当の質問は次のように傾いていると思います。

CFGRID は、CFGRIDUPDATE を介して複数のテーブル/動的列を更新できますか?

短い答え:いいえ

長い回答: はい。ただし、CFGRIDUPDATE 経由ではありません。むしろ、CFQUERY 経由で、CFC バインドと CFAJAXPROXY 経由で CFGRID をもう少し処理します。

解決:

1) このソリューションには 2 つのファイルが必要です。ファイル #1 は、クエリ機能をラップするコンポーネントです。私たちはそれを呼びますcfgrid.cfc

<cfcomponent>

    <cfset this.dsn = "gridexample" />

    <cffunction name="getUsers" returntype="any" access="remote" output="false">
        <cfargument name="page" />
        <cfargument name="pageSize" />
        <cfargument name="gridsortcolumn" />
        <cfargument name="gridsortdirection" />

        <cfset var getUsers = 0 />

        <cfquery name="getUsers" datasource="#this.dsn#">
            SELECT Users.UserID, Users.FirstName, UserCategories.Category_ID
            FROM Users
        INNER JOIN UserCategories ON (Users.User_ID = UserCategories.UserID)

            <cfif arguments.gridsortcolumn neq "" or arguments.gridsortdirection neq ""> 
                order by #arguments.gridsortcolumn# #arguments.gridsortdirection#
                </cfif> 
        </cfquery>

        <cfreturn QueryConvertForGrid(getUsers, page, pageSize) />
    </cffunction>

    <cffunction name="addNewUser" returntype="string" access="remote" output="false">
        <cfargument name="fullname" type="string" required="true" />
        <cfargument name="category_id" type="numeric" required="true" />

        <cfquery datasource="#this.dsn#">
        INSERT INTO Users
        (
            fullname
        )
        VALUES
        (
            <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.fullname#">
        )
        </cfquery>

        <cfquery name="getPkey" datasource="#this.dsn#">
        SELECT Max(User_ID) as PKey
        FROM Users
        </cfquery>

        <cfquery datasource="#this.dsn#">
        INSERT INTO UserCategories
        (
            User_ID,
            Category_ID
        )
        VALUES
        (
            <cfqueryparam cfsqltype="cf_sql_integer" value="#getPKey.PKey#" />
            <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.category_id#" />
        )
        </cfquery>

        <cfreturn "User Added" />
    </cffunction>

    <cffunction name="editUser" access="remote">
        <cfargument name="gridaction">
        <cfargument name="gridrow">
        <cfargument name="gridchanged"> 

    </cffunction>

</cfcomponent>

CFC の次の主要部分に注意してください。

a) getUsers() は、現在のユーザー データとその CategoryID を返します。スキーマに合わせてこのクエリを書き直す必要がありますが、重要なことは、これはデータ作成クエリであるため、ユーザーの作成に必要なすべてのデータは、ユーザーの更新にも存在する必要があるということです。これは、User ごとに CategoryID が 1 つしかないことも前提としています (多くの開発者は、CategoryID を Users テーブルに残すことで非正規化しますが、それはあなたの裁量に任せます)。

b) addNewUser() は、フォーム/グリッドの送信が新しい名前 (category_id と同様に) を渡すことを期待しますが、Category_ID を人が記入するように要求するつもりはないことを前もって知っています。フォーム/グリッド データの入力 - プログラムで行います。ただし、最終結果は同じです。クエリは両方の値を知る必要があります。簡潔にするために、<CFTRANSACTION>呼び出しは省略しましたが、覚えておいてください。3 つのクエリを連続して実行しようとしています。そのうちの 1 つ (3 つ目) は、もう 1 つの動的データ (1 つ目と 2 つ目) に依存しています。したがって、このタイプの設計を進めるときは、並行性を念頭に置く必要があります。

c) 今のところ、editUser() を無視してください。後で入力する必要があります。このデモンストレーションが機能するためには、単に存在する必要があります。

2) 必要な 2 番目のファイルはフロント エンドです。グリッド自体です。これを cfgrid.cfm と呼びます。

これは非常に大きく、コードの各チャンクについて説明が必要になるため、上から下に説明します。

<cfparam name="URL.Category_ID" default=4 />

テンプレートの最初の行では、URL 変数をパラメーター化しています。これを使用して、新しいユーザーにバックグラウンドで割り当てをプログラムで提供します。独自のメカニズムを使用して、動的な Category_ID を必要に応じて提供します。

<cfajaxproxy cfc="cfgrid" jsclassname="dataproxy">

この行により、ColdFusion は「dataproxy」という名前の JavaScript オブジェクトを作成し、それを指す CFC に存在するコア関数へのアクセスを提供するために必要なコンテナーにラップします...そしてこの場合、「cfgrid」を指すことになります。これは、上記の最初のファイル (cfgrid.cfc) です。したがって、getUsers() メソッドと addNewUser() メソッドを備えた JavaScript オブジェクトがあることを期待できます。

<html>
<head>
<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/package/toolbar/toolbar.js"></script>

ここで、HTML ドキュメント タグを開始し、ColdFusion に含まれる Ajax ライブラリの 1 つである toolbar.js ファイルへの参照を含めます。

<script type="text/javascript">
var dataproxy = new dataproxy();

dataproxy.setCallbackHandler(handleResult);

function handleResult(response)
{
    alert(response);
}

ここで、dataproxy オブジェクトのローカル インスタンスを作成し (<CFAJAXPROXY>呼び出しから上記を思い出してください)、別の JavaScript 関数 'handleResult' を指すコールバック ハンドラーを割り当てます。これは、 Ajax での作業の基本部分である非同期通信を扱うときに使用するプロセスです。

function init()
{
    grid = ColdFusion.Grid.getGridObject("UserGrid");

    var gridHead = grid.getView().getHeaderPanel(true);

    var tbar = new Ext.Toolbar(gridHead);

    tbar.addButton({text:"Add User", handler:onAdd });
}

この init() 関数は、cfgrid への通信を駆動するために必要な JavaScript オブジェクトを作成します。ColdFusion.Grid.getGridObject を介して cfgrid への参照を取得し、そこからグリッドのヘッダーにアクセスします。これにより、ツールバーをターゲットにすることができ、[ユーザーの追加] ボタンを追加して、プログラムで新しい関数を呼び出すことを決定します。クリックすると...その機能の名前は「onAdd」...

function onAdd(button,event)
{
    ColdFusion.Window.show('addUserWin');
}

当然のことながら、ここに onAdd() 関数があり、ユーザーを追加するための新しいウィンドウ (ユーザーのフルネームの入力フィールドを含むウィンドウ) を表示します。

最後に、上記の新しい AddUserWin ウィンドウには、ユーザーを追加するための独自の関数が必要になります。これは、Category_ID をユーザーに提供させるのではなく、動的に提供する必要があるためです。したがって、 addUser() はまさにそれを行います:

function addUser()
{
    var f = document.frmUser;

    dataproxy.addNewUser(
        f.txtFullname.value,
        f.txtCategory_ID.value
    );

    ColdFusion.Window.hide('addUserWin');

    grid.refresh();
}
</script>
</head>

addUser() では、<FORM>以下をその名前 (frmUser) で参照し、JavaScript プロキシ オブジェクトの addNewUser() メソッドを呼び出します。これは CFC にマップされます。予想どおり、新しいユーザーの値を知る必要があるため、txtFullname と txtCategory_ID の値を渡します。ウィンドウを非表示にしてグリッドを更新して終了します。

ここでは非同期であるため、結果を読み取って表示する必要はありません。その結果は、上記の handleResult() メソッドで割り当てられたコールバック ハンドラを介して起動されます。

次に、 の母集団を養う引数を作成しますCFGRID

<cfset args = StructNew() />

<cfset args.name = "UserGrid" />
<cfset args.format = "html" />
<cfset args.bindOnLoad = "true" />
<cfset args.bind = "cfc:cfgrid.getUsers({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})" />
<cfset args.selectmode = "edit" />
<cfset args.onchange = "cfc:cfgrid.editUser({cfgridaction},{cfgridrow},{cfgridchanged})" />

ここでは: 1. グリッドに「UserGrid」という名前を付けます (上記の JavaScript でその名前で参照したように)、2. html を使用してレンダリングさせ、3. ページの読み込み時にデータをバインドするように指示します。4. バインドします。 cfgrid.cfc を介してそのデータを取得し、getUsers() メソッドを呼び出します (そして、page、pagesize、sortcolumn、および sortdirection の値を介して cfgrid の現在のパラメーターを渡します)。5. 編集可能にします。6. onChange ハンドラーを割り当てます。 、ユーザーの編集も許可したい場合に備えて。この最後の部分は (残念ながら) 必要なので、この例では取り除くことができませんでした。

<CFFORM>次に、 andをビルドします<CFGRID>

<cfform>
    <cfgrid attributeCollection="#args#">
        <cfgridcolumn name="User_ID" display="false">
        <cfgridcolumn name="Category_ID" display="false">
        <cfgridcolumn name="FullName" header="Full Name">
    </cfgrid>
</cfform>

ここで、上で指定した引数をグリッドに入力します。グリッドには「FullName」フィールドのみが表示されますが、User_ID と Category_ID はまだ存在し、データセットの一部であることに注意してください。それらは単にフロントエンドに表示されません。

最後になりましたが、ユーザーが「新しいユーザーを追加」ボタンをクリックしたときにポップアップするウィンドウは、ユーザーの入力を許可するために必要なインターフェイスを提供すると同時に、(舞台裏で)Category_ID が何であるかを制御します動的に提供される:

<cfwindow name="addUserWin" modal="true" resizable="false" title="Add New User">
    <form name="frmUser">
<input type="hidden" name="txtCategory_ID" value="<cfoutput>#URL.Category_ID#</cfoutput>" />
    <table width="100%">
        <tr>
            <td>Fullname</td>
            <td><input type="text" name="txtFullname" value=""></td>
        </tr>
        <tr>
            <td colspan="2"><input type="button" value="Add User" onclick="javascript:addUser();"></td>
        </tr>
    </form>
</cfwindow>

この CFWINDOW への呼び出しは、フォームをカプセル化するために必要な「ポップアップ」を提供します。上記のコードで参照したように、フォーム名は frmUser であることに注意してください。また、フィールドの名前は、JavaScript で参照されるものと一致する (大文字と小文字を含む) ことに注意してください。このフォームはユーザーが入力する Fullname フィールドを表示しますが、Category_ID は非表示のままですが、このコード例の上部にある URL パラメーターを介して、プログラムによって駆動されます。最後に、ボタンをクリックすると addUser() メソッドが呼び出されます。このメソッドは、javascript オブジェクトと対話し、次に CFC と対話し、データをデータベースにコミットします。

最後に、このテンプレートを完成させる直前に、init() JavaScript 関数を起動することを忘れないでください!

<cfset ajaxOnLoad("init")>

</html>

お役に立てれば。

cfgrid html 形式の CRUDから適応(出典: Anuj Gakhar)

于 2011-12-07T06:15:24.550 に答える
2

別の方法があります。CFGRID によってポストされたフォーム変数を直接処理する必要があります。コード例を次に示します。

フォーム.cfm:

<cfform method="post" action="post.cfm">
<cfoutput><input type="hidden" name="ParentID" value="#ParentID#"></cfoutput>
<cfgrid format="html" name="GridData" query="Records" insert="yes" delete="yes" selectmode="edit">
    <cfgridcolumn name="RecordID" display="no">
    <cfgridcolumn name="RecordName" width="150" header="Name" headeralign="left" dataalign="left" select="Yes" display="Yes">
    <cfgridcolumn name="RecordColor" width="150" header="Color" headeralign="left" dataalign="left" select="Yes" display="Yes">
</cfgrid>
<br />
<input type="submit" value="Save Records" />
</cfoutput>
</cfform>

その後、post.cfm で

<cfif isDefined("GridData.RowStatus.Action") and isArray(GridData.RowStatus.Action)>
    <cfloop from="1" to="#ArrayLen(GridData.RowStatus.Action)#" index="i">
        <cfswitch expression="#GridData.RowStatus.Action[i]#">
            <cfcase value="I">
                <cfquery name="Records_INSERT" datasource="#request.maindatasource#" blockfactor="100">
                    INSERT INTO Records (RecordName, RecordColor, RecordParent)
                    VALUES (
                        <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordName[i])#">,
                        <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordColor[i])#">,
                        <cfqueryparam cfsqltype="cf_sql_integer" value="#Val(ParentID)#">
                    )
                </cfquery>
            </cfcase>
            <cfcase value="U">
                <cfquery name="Records_UPDATE" datasource="#request.maindatasource#" blockfactor="100">
                    UPDATE Records
                    SET
                        RecordName = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordName[i])#">,
                        RecordColor = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordColor[i])#">
                    WHERE
                        RecordID=<cfqueryparam cfsqltype="cf_sql_integer" value="#GridData.original.RecordID[i]#">
                </cfquery>
            </cfcase>
            <cfcase value="D">
                <cfquery name="Records_DELETE" datasource="#request.maindatasource#" blockfactor="100">
                    DELETE
                    FROM Records
                    WHERE
                        RecordID=<cfqueryparam cfsqltype="cf_sql_integer" value="#GridData.original.RecordID[i]#">
                </cfquery>
            </cfcase>
        </cfswitch>
    </cfloop>
</cfif>
于 2012-01-19T17:06:06.563 に答える