« やる夫がデザインパターンをやるようです 第8回 | メイン | 咲と五月女の「咲」が3代目になります。 »



SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方)

SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方)をはてなブックマークに追加 SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方)をdel.icio.usに追加  Yahoo!ブックマークに登録 SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方)をGoogle Bookmarksに追加 SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方)をtwitterにポスト
SharePointExtJSGrid.PNG やる夫で学ぶデザインパターンのアブストラクトファクトリをやるつもりでしたが、ちょっと横道にそれます。SharePointのフォームを自前で作るというエントリの続きです。
ExtJSにはEditorGridPanelというものがあるのですが、エクセルのような表をフォームとして扱えるウィジェットです。これをSharePointのフォームとして扱えれば、データシートビューのようなフォームが作れてしまいます。基本的にはLists.asmxのUpdateListItemsを使っているのですが、まとめて更新、新規作成なんかができちゃうので、ちゃんと作りこめばかなり便利なものになるかと思いますよ。
いかにサンプルソースを載せておきます。簡単ではありますが、ソースにコメントを残しておきました。ご自身の環境に合わせてパスなどを書き換えてみてください。また、このサンプルソースをそのまま使う場合はSharePoint側でライブラリ(カスタムリストかな)を作る際のフィールド名などもあわせてください。(ソースに記述しておきました。)
<link rel="stylesheet" type="text/css" href="<yourSitePath>/ext/resources/css/ext-all.css" />
<script type="text/javascript" src="<yourSitePath>/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="<yourSitePath>/ext/ext-all.js"></script>
<script type="text/javascript">
function getHttpReq(){
    return window.XMLHttpRequest ? new XMLHttpRequest() : ( function() {
        try        { return new ActiveXObject( "Msxml2.XMLHTTP" );    }
        catch( e ) { return new ActiveXObject( "Microsoft.XMLHTTP" ); }
    }());
}

function getFieldItems()
{
    var dataAry = new Array();
    var libName = '<yourLibName>'

    // SharePointでのフィールド定義
    var targetFields = 
    '<FieldRef Name="ID" />' +          // デフォルト
    '<FieldRef Name="Title" />' +       // デフォルト
    '<FieldRef Name="selectClmn" />' +  // 選択肢フィールドを"selectClmn"で作成しておく
    '<FieldRef Name="numField" />' +    // 数値フィールドを"numField"で作成しておく
    '<FieldRef Name="dateField" />';    // 日付フィールドを"dateField"で作成しておく

    var httpInst = getHttpReq();
    httpInst.open( "POST", "<yourSitePath>/_vti_bin/Lists.asmx", false );
    httpInst.setRequestHeader( 'Content-Type','text/xml; charset=utf-8' );
    httpInst.setRequestHeader( 'SOAPAction','http://schemas.microsoft.com/sharepoint/soap/GetListItems' );
    var postBody = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>' + libName + '</listName><viewName></viewName><query></query><viewFields><ViewFields>' + targetFields + '</ViewFields></viewFields><rowLimit></rowLimit><queryOptions><QueryOptions/></queryOptions><webID></webID></GetListItems></soap12:Body></soap12:Envelope>';

    httpInst.onreadystatechange = function()
    {
        if ( httpInst.readyState == 4 ){
            xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
            xmlDoc.async = false;
            xmlDoc.loadXML( httpInst.responseText );
            var rowsItem = xmlDoc.selectNodes( '/soap:Envelope/soap:Body/GetListItemsResponse/GetListItemsResult/listitems/rs:data/z:row' );

            for( idx = 0; idx < rowsItem.length; idx++ ){
                var fieldDataList = new Array();

                // 日付フィールドは "2008-04-07 13:00:00"で返ってくるので
                // "2008/04/07"にフォーマットを変換しておく。
                var dateRow = rowsItem[ idx ].getAttribute( "ows_dateField" ).replace( /-/g, "/" );
                dateRow = dateRow.substring( 0, dateRow.lastIndexOf( " " ) );

                // 数値フィールドは 0.0000000・・・で返ってくるのでroundする。
                var numRow = Math.round( rowsItem[ idx ].getAttribute( "ows_numField" ) );
                fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_ID" ) );
                fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_Title" ) );
                fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_selectClmn" ) );
                fieldDataList.push( numRow );
                fieldDataList.push( dateRow );
                dataAry.push( fieldDataList );
            }
        }
    }
    httpInst.send( postBody );
    return dataAry;
}

function updateListItems( paramXML )
{
    var httpInst = getHttpReq();
    var libName = '<yourLibName>';
    httpInst.open( "POST", "<yourSitePath>/_vti_bin/Lists.asmx", false );
    httpInst.setRequestHeader( 'Content-Type','text/xml; charset=utf-8' );
    httpInst.setRequestHeader( 'SOAPAction','http://schemas.microsoft.com/sharepoint/soap/UpdateListItems' );

    var postBody = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>' + libName + '</listName><updates>' + paramXML + '</updates></UpdateListItems></soap:Body></soap:Envelope>';
/*
    httpInst.onreadystatechange = function()
    {
        // エラーハンドリングはここで行う。
        if ( httpInst.readyState == 4 ){
        }
    }
*/
    httpInst.send( postBody );
    alert( "更新しました" );
}


Ext.onReady( function(){

    var changeList = new Array();

    var headAry = [
        { name : 'ID' },
        { name : 'Title' },
        { name : 'selectClmn' },
        { name : 'numField' },
        { name : 'dateField', type:'date', dateFormat: 'Y/m/d' }
    ];

   var clmn = new Ext.grid.ColumnModel([
        { 
            id : 'ID',
            header: "ID",
            dataIndex: 'ID',
            width: 50 
        },
        { 
            header: "タイトル", 
            dataIndex: 'Title', 
            width: 100, 
            editor: new Ext.form.TextField( 
            {
                allowBlank: false
            }) 
        },
        {
            // 選択肢フィールド定義はHTML下部のid:ddfieldより取得する。
            header: "選択肢フィールド", 
            dataIndex: 'selectClmn', 
            width: 100, 
            editor: new Ext.form.ComboBox({
                typeAhead: true,
                triggerAction: 'all',
                transform:'ddfield',
                lazyRender:true
             })
        },
        {
            header: "数値フィールド",
            dataIndex: 'numField',
            width: 100,
            align: 'right',
            editor: new Ext.form.NumberField()
        },
        {
            header: "日付フィールド",
            dataIndex: 'dateField',
            width: 120,
            renderer: Ext.util.Format.dateRenderer( 'Y/m/d' ),
            editor: new Ext.form.DateField( { format: 'Y/m/d' } )
        }
    ]);
    clmn.defaultSortable = true;

    var MyForm = Ext.data.Record.create( headAry );
    var reader = new Ext.data.ArrayReader( {}, headAry );
    var store = new Ext.data.Store({
        reader: reader,
        data: getFieldItems(),
        sortInfo:{ field:'ID', direction:'DESC' }
    });

    var grid = new Ext.grid.EditorGridPanel({
        store: store,
        cm: clmn,
        renderTo: 'editor-grid',
        width:640,
        height:300,
        title:'Form',
        frame:true,
        clicksToEdit:1,
        stripeRows:true,

        // リスナー登録。
        listeners:{

            // gridセルに対する編集が加わった際のイベントを取得する。
            'afteredit': function( evt ) {

                var curChange = grid.getStore().getAt( evt.row ).get( 'ID' );

                // 編集が加わったIDを参照して、空の場合は新規作成とする
                if( curChange == '' ) return;

                // 既存のアイテムで編集されたIDをためておく。
                for( var idx = 0; idx < changeList.length; idx++ ){
                    if( changeList[ idx ] == curChange ){
                        return;
                    }
                }
                changeList.push( curChange );
            }
        },

        // ツールバー。「新規作成」と「送信」
        tbar: [{
            text: '新規作成',
            handler : function(){
                var newForm = new MyForm({
                    ID:'',
                    Title: '',
                    selectClmn: '',
                    numField: 0,
                    dateField: ( new Date() ).clearTime()
                });
                grid.stopEditing();
                store.insert( 0, newForm );
                grid.startEditing( 0, 0 );
            }
        },
        {
            text: '送信',
            handler : function(){
                var idx = 0;
                var methodCnt = 1;
                var batchXML = '';
                var curStore = grid.getStore();
                curStore.each( function(){

                    // 新規作成はIDが空
                    if( curStore.getAt( idx ).get( 'ID' ) == '' ){
                        var fmtDate = Ext.util.Format.date( curStore.getAt( idx ).get( 'dateField' ), 'Y-m-d' );
                        batchXML = batchXML + 
                        '<Method ID="' + methodCnt + '" Cmd="New">' +
                        '<Field Name="Title">' + curStore.getAt( idx ).get( 'Title' ) + '</Field>' +
                        '<Field Name="selectClmn">' + curStore.getAt( idx ).get( 'selectClmn' ) + '</Field>' +
                        '<Field Name="numField">' + curStore.getAt( idx ).get( 'numField' ) + '</Field>' +
                        '<Field Name="dateField">' + fmtDate + '</Field>' +
                        '</Method>'
                        methodCnt++;
                    }
                    
                    // 既存のアイテムを変更した場合、
                    // aftereditイベントでためたIDを参照してXMLを構築する。
                    else {
                        for( var sdx = 0; sdx < changeList.length; sdx++ ){
                            if( curStore.getAt( idx ).get( 'ID' ) == changeList[ sdx ] ){
                                
                                // SharePointの日付フォーマットに直す。"2008/04/07" → "2008-04-07"
                                var fmtDate = Ext.util.Format.date( curStore.getAt( idx ).get( 'dateField' ), 'Y-m-d' );

                                batchXML = batchXML + 
                                '<Method ID="' + methodCnt + '" Cmd="Update">' +
                                '<Field Name="ID">' + curStore.getAt( idx ).get( 'ID' ) + '</Field>' +
                                '<Field Name="Title">' + curStore.getAt( idx ).get( 'Title' ) + '</Field>' +
                                '<Field Name="selectClmn">' + curStore.getAt( idx ).get( 'selectClmn' ) + '</Field>' +
                                '<Field Name="numField">' + curStore.getAt( idx ).get( 'numField' ) + '</Field>' +
                                '<Field Name="dateField">' + fmtDate + '</Field>' +
                                '</Method>'
                                methodCnt++;
                            }
                        }
                    }
                    idx++;
                });

                // 新規作成や、更新があった場合はmethodCntが1以上
                if( methodCnt > 1 ){
                    // XMLを渡して更新する。
                    updateListItems( '<Batch>' + batchXML + '</Batch>' );

                    // リロードしてgridフォームを読み直すと更新されてます。
                    // location.reload();
                }
                else {
                    alert( "フォームの更新がされていません" );
                }
            }
        }]
    });
});
</script>
</head>
<body>
<div style="margin: 12px 12px">
<div id="editor-grid"></div>
<select name="ddfield" id="ddfield" style="display: none;">
    <option value="hoge">hoge</option>
    <option value="moge">moge</option>
    <option value="fuga">fuga</option>
</select>
</div>
</body>

★このコンテンツに目的の情報はありませんでしたか?


[ 最近のエントリーとその関連エントリー ]


[ スポンサードリンク ]

トラックバック

このエントリーのトラックバックURL:
http://mojalog.com/cgi/mt/mt-tb.cgi/262

コメントを投稿

ツリータイプ・カテゴリー

open all | close all

リファラから検索


サイト内検索