[SharePoint 2010 開発] ダイアログフレームワーク、Client OM (JavaScript) を使った開発


環境 : SharePoint Foundation 2010 (Beta 2), Visual Studio 2010 (Beta 2)

<<SharePoint 2010 開発 新機能>>

こんにちは。

今日は、セッションでご紹介した SharePoint 2010 ダイアログフレームワークを使用した JavaScript の実装方法について (セッションでのコードを) ご紹介します。

ダイアログフレームワークは、ご説明したように .aspx で作成されたフォームを表示することが可能です。このため、.aspx でページを作成しておき、ダイアログフレームワークを使用して表示したり、従来通り (SharePoint Server 2007 形式で) Web フォームとして表示したり、といった選択ができます。

例えば、SharePoint 2010 でリストを作成し、[リストの設定] で [詳細設定] を開くと、ダイアログフレームワークでフォームを開くか、従来通り Web フォームを使って開くか、といった選択をおこなうことができます。(下図)

では早速、SharePoint 2010 / Visual Studio 2010 を使用したこの JavaScript の開発体験について簡単なサンプルを記述します。まずは、ダイアログフレームワークの勉強の前に、Client OM (Client Object Model) を使用した簡単なサンプルを見てみます。

Visual Studio で ビジュアル Web パーツ (可視 Web パーツ) のプロジェクトを新規作成し、VisualWebPart1UserControl.ascx のマークアップを表示して、SharePoint の JavaScript ライブラリが使えるように以下の1 行を追加します。

<SharePoint:ScriptLink ID="ScriptLink1" runat="server" Name="sp.js" Localizable="false" LoadAfterUI="true" />

つぎに、以下の通りマークアップを記述します。
使用している API の詳細は MSDN を見ていただくとわかりますが、SP 名前空間の SharePoint 2010 の JavaScript  API を使用して、「Projects」という名前のリストから全件を取得し (Id, DisplayName, Title, Description, DueDate, PrimaryContact の列を取得しています)、取得した結果を最後の <table> タグの中に追加しています。

AJAX ですので、検索結果は非同期で取得されるという点に注意してください。(検索が終了すると、非同期で下記の onListsLoaded 関数が呼び出されます。)

<script language="ecmascript" type="text/ecmascript">
    var context;            // クライアントコンテキスト
    var web;                // SPWeb
    var ProjectsList;       // Project リストオブジェクト
    var ProjectListItems;   // Project リストアイテム一覧

    _spBodyOnLoadFunctionNames.push("Initialize()");

    // JavaScript で SP 名前空間のオブジェクトが使える ! (ただし、弱い型付け)
    function Initialize() {
        // 基礎となるオブジェクトの取得
        context = SP.ClientContext.get_current();
        web = context.get_web();

        // Projects リストの取得
        ProjectsList = web.get_lists().getByTitle("Projects");

        // Projects リストアイテムの取得 
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>50</RowLimit></View>");
        ProjectListItems = ProjectsList.getItems(camlQuery);

        // クエリ時にオブジェクトのロードを指示
        context.load(ProjectsList);
        context.load(ProjectListItems, "Include(Id, DisplayName, Title, Description, DueDate, PrimaryContact)");

        // クエリ実行
        context.executeQueryAsync(Function.createDelegate(this, this.onListsLoaded));
    }

    function onListsLoaded(sender, args) {
        var ProjectCount = ProjectListItems.get_count();

        var ProjectsTable = document.getElementById("tblProjectsList");

        // テーブル (table) の内容をいったん削除
        while (ProjectsTable.rows.length > 0)
            ProjectsTable.deleteRow(ProjectsTable.rows.length - 1);

        var row = new Array();  // HTML の行
        var content;            // HTML のコンテンツ
        var cell;               // HTML のテーブルのセル (td)

        // 取得した Projects の内容を table に追加
        var tbo = document.createElement('tbody');
        for (ProjectIndex = 0; ProjectIndex < ProjectCount; ProjectIndex++) {
            row[ProjectIndex] = document.createElement('tr');

            var ProjectLI = ProjectListItems.itemAt(ProjectIndex);
            var ProjectTile = ProjectLI.get_item("Title");
            var ProjectDueDate = ProjectLI.get_item("DueDate");
            var ProjectDescription = ProjectLI.get_item("Description");
            var ProjectPrimaryContact = ProjectLI.get_item("PrimaryContact");

            cell = document.createElement('td');
            content = document.createTextNode(ProjectTile);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDueDate);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDescription);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectPrimaryContact);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            tbo.appendChild(row[ProjectIndex]);
        }
        ProjectsTable.appendChild(tbo);
    }
    
</script>
<div style="font-weight: bold">プロジェクトの一覧</div>
<hr />
<table id="tblProjectsList" border="1">    
</table>

この Web パーツを配置して表示すると、下図の Projects リストの一覧が Web パーツとして設定されます。

JavaScript (ECMAScript) の Client OM では、%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS の SP.js、SP.Core.js、SP.Ribbon.js、SP.Runtime.js が使用されており、SharePoint Foundation のマスターページの ScriptManager の ScriptMode を使用して、SP.debug.js、SP.Core.debug.js、SP.Ribbon.debug.js、SP.Runtime.debug.js を使用することもできます。

つぎに、ここでの本題であるダイアログフレームワークを確認してみましょう。

例えば、試しに以下の通りコードを書き変えてみます。(太字が変更した部分です。)
何をおこなったかというと、一番最後の行に [ダイアログを表示 !] というリンクを追加し、このリンクをクリックした際に、SharePoint 2010 が持っているリストアイテムの表示画面 (DispForm.aspx) を決め打ちで表示するという簡単なサンプルです。(通常は、選択したアイテムに応じてそのアイテムの表示をおこなうと良いでしょう。。。これはあくまでもサンプルですので、アイテムの ID も決め打ちで表示しています。)

<script language="ecmascript" type="text/ecmascript">
    var context;            // クライアントコンテキスト
    var web;                // SPWeb
    var ProjectsList;       // Project リストオブジェクト
    var ProjectListItems;   // Project リストアイテム一覧
    var modalDialog;        // モーダルダイアログ

    _spBodyOnLoadFunctionNames.push("Initialize()");

    // JavaScript で SP 名前空間のオブジェクトが使える ! (ただし、弱い型付け)
    function Initialize() {
        // 基礎となるオブジェクトの取得
        context = SP.ClientContext.get_current();
        web = context.get_web();

        // Projects リストの取得
        ProjectsList = web.get_lists().getByTitle("Projects");

        // Projects リストアイテムの取得 
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>50</RowLimit></View>");
        ProjectListItems = ProjectsList.getItems(camlQuery);

        // クエリ時にオブジェクトのロードを指示
        context.load(ProjectsList);
        context.load(ProjectListItems, "Include(Id, DisplayName, Title, Description, DueDate, PrimaryContact)");

        // クエリ実行
        context.executeQueryAsync(Function.createDelegate(this, this.onListsLoaded));
    }

    function onListsLoaded(sender, args) {
        var ProjectCount = ProjectListItems.get_count();

        var ProjectsTable = document.getElementById("tblProjectsList");

        // テーブル (table) の内容をいったん削除
        while (ProjectsTable.rows.length > 0)
            ProjectsTable.deleteRow(ProjectsTable.rows.length - 1);

        var row = new Array();  // HTML の行
        var content;            // HTML のコンテンツ
        var cell;               // HTML のテーブルのセル (td)

        // 取得した Projects の内容を table に追加
        var tbo = document.createElement('tbody');
        for (ProjectIndex = 0; ProjectIndex < ProjectCount; ProjectIndex++) {
            row[ProjectIndex] = document.createElement('tr');

            var ProjectLI = ProjectListItems.itemAt(ProjectIndex);
            var ProjectTile = ProjectLI.get_item("Title");
            var ProjectDueDate = ProjectLI.get_item("DueDate");
            var ProjectDescription = ProjectLI.get_item("Description");
            var ProjectPrimaryContact = ProjectLI.get_item("PrimaryContact");

            cell = document.createElement('td');
            content = document.createTextNode(ProjectTile);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDueDate);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDescription);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectPrimaryContact);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            tbo.appendChild(row[ProjectIndex]);
        }
        ProjectsTable.appendChild(tbo);
    }

    // ダイアログフレームワークを使ってます。。。
    function ShowDialogTest() {
        var options = {
            url: '/sites/officedemo/Lists/Projects/DispForm.aspx?ID=1&Source=http%3A%2F%2Fkkdeveva07%2Fsites%2Fofficedemo%2FLists%2FProjects%2FAllItems%2Easpx&ContentTypeId=0x010054B0557C6CE4F6429E81198A78E56E5F',
            tite: 'Update Peoject (Test)',
            allowMaximize: false,
            showClose: false,
            width: 800,
            height: 600,
            dialogReturnValueCallback: testCallback };
        modalDialog = SP.UI.ModalDialog.showModalDialog(options);
    }

    function testCallback() {
        SP.UI.Notify.addNotification('Callback is called !');
    }

</script>
<div style="font-weight: bold">プロジェクトの一覧</div>
<hr />
<table id="tblProjectsList" border="1">    
</table>
<a href="javascript:ShowDialogTest()">ダイアログを表示!</a>

この Web パーツを表示すると、テーブルの下に [ダイアログを表示 !] をいうリンクが表示され、このリンクをクリックすると、下図の通り SharePoint 2010 の既定のアイテム表示画面 (DispForm.aspx) がダイアログフレームワークで表示されます。(そして、ここでは、ちゃんとアイテムの編集もおこなうことができます。)

上記の testCallback 関数をみていただくと、SP.UI.Notify.addNotification を呼び出していますね。よって、ダイアログを終了すると、常に、右側に、黄色で下図のような Notify メッセージが表示されます。(この Notify メッセージは、時間がたつと自然に消えます。。。) このように、通知エリアやステータスバーも JavaScript で簡単に操作することができます。

このようにダイアログフレームワークでは .aspx ページをそのまま表示することが可能です。しかし、.aspx ページ (Web フォーム) だけでなく、HTML 内の特定の要素 (element) だけをダイアログフレームワークで表示することもできます。

以下のサンプルを見てください。(変更箇所をまた太字で記載します。)
ここでは、.aspx ページ全体を表示するのではなく、divAddProjects という id の要素 (div タグ) を HTML 上に用意しておき (非表示としておきます)、これを複製 (cloneNode) して表示 (style.display="block") させて、処理が終わったら複製したアイテムを再度 HTML のノードとして設定しなおします。(これは、セッションのデモでご紹介したサンプルコードそのものです。)

<script language="ecmascript" type="text/ecmascript">
    var context;            // クライアントコンテキスト
    var web;                // SPWeb
    var ProjectsList;       // Project リストオブジェクト
    var ProjectListItems;   // Project リストアイテム一覧
    var modalDialog;        // モーダルダイアログ
    var copyOfAddProjectsForm;

    _spBodyOnLoadFunctionNames.push("Initialize()");

    // JavaScript で SP 名前空間のオブジェクトが使える ! (ただし、弱い型付け)
    function Initialize() {
        // 基礎となるオブジェクトの取得
        context = SP.ClientContext.get_current();
        web = context.get_web();

        // Projects リストの取得
        ProjectsList = web.get_lists().getByTitle("Projects");

        // Projects リストアイテムの取得 
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>50</RowLimit></View>");
        ProjectListItems = ProjectsList.getItems(camlQuery);

        // クエリ時にオブジェクトのロードを指示
        context.load(ProjectsList);
        context.load(ProjectListItems, "Include(Id, DisplayName, Title, Description, DueDate, PrimaryContact)");

        // クエリ実行
        context.executeQueryAsync(Function.createDelegate(this, this.onListsLoaded));
    }

    function onListsLoaded(sender, args) {
        var ProjectCount = ProjectListItems.get_count();

        var ProjectsTable = document.getElementById("tblProjectsList");

        // テーブル (table) の内容をいったん削除
        while (ProjectsTable.rows.length > 0)
            ProjectsTable.deleteRow(ProjectsTable.rows.length - 1);

        var row = new Array();  // HTML の行
        var content;            // HTML のコンテンツ
        var cell;               // HTML のテーブルのセル (td)

        // 取得した Projects の内容を table に追加
        var tbo = document.createElement('tbody');
        for (ProjectIndex = 0; ProjectIndex < ProjectCount; ProjectIndex++) {
            row[ProjectIndex] = document.createElement('tr');

            var ProjectLI = ProjectListItems.itemAt(ProjectIndex);
            var ProjectTile = ProjectLI.get_item("Title");
            var ProjectDueDate = ProjectLI.get_item("DueDate");
            var ProjectDescription = ProjectLI.get_item("Description");
            var ProjectPrimaryContact = ProjectLI.get_item("PrimaryContact");

            cell = document.createElement('td');
            content = document.createTextNode(ProjectTile);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDueDate);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectDescription);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            cell = document.createElement('td');
            content = document.createTextNode(ProjectPrimaryContact);
            cell.appendChild(content);
            row[ProjectIndex].appendChild(cell);

            tbo.appendChild(row[ProjectIndex]);
        }
        ProjectsTable.appendChild(tbo);
    }

    // ダイアログフレームワークを使ってます。。。
    function ShowDialogTest() {
        var divAddProjects = document.getElementById("divAddProjects");

        copyOfAddProjectsForm = divAddProjects.cloneNode(true);

        divAddProjects.style.display = "block";
        var options = {
            html: divAddProjects,
            width: 350,
            height: 450,
            dialogReturnValueCallback: testCallback
        };
        modalDialog = SP.UI.ModalDialog.showModalDialog(options);
    }

    function testCallback() {
        SP.UI.Notify.addNotification('Callback is called !');
        document.body.appendChild(copyOfAddProjectsForm);
    }

    function AddProjects() {
        var lici1 = new SP.ListItemCreationInformation();
        var AddedItem = ProjectsList.addItem(lici1);
        AddedItem.set_item("Title", document.getElementById("txtTitle").value);
        AddedItem.set_item("DueDate", new Date(document.getElementById("txtDueDate").value));
        AddedItem.set_item("Description", document.getElementById("txtDescription").value);
        AddedItem.set_item("PrimaryContact", document.getElementById("txtPrimaryContact").value);
        AddedItem.update();
        context.load(AddedItem);
        context.executeQueryAsync(onProjectsAdded);
    }

    function onProjectsAdded(args) {
        modalDialog.close();
        Initialize();
    }
</script>
<div style="font-weight: bold">プロジェクトの一覧</div>
<hr />
<table id="tblProjectsList" border="1">
</table>
<a href="javascript:ShowDialogTest()">ダイアログを表示!</a>
<br /> 
<div id="divAddProjects" style="display: none">
    <table>
        <tr>
            <td>
                名前
            </td>
        </tr>
        <tr>
            <td>
                <input type="text" id="txtTitle" />
            </td>
        </tr>
        <tr>
            <td>
                期限
            </td>
        </tr>
        <tr>
            <td>
                <input type="text" id="txtDueDate" />
            </td>
        </tr>    
        <tr>
            <td>
                内容
            </td>
        </tr>
        <tr>
            <td>
                <input type="text" id="txtDescription" />
            </td>
        </tr>    
        <tr>
            <td>
                主担当者
            </td>
        </tr>
        <tr>
            <td>
                <input type="text" id="txtPrimaryContact" />
            </td>
        </tr>    
        <tr>
            <td>
                <input type="button" value="新しいプロジェクトを追加" onclick="AddProjects()" />
            </td>
        </tr>
    </table>
</div>

この Web パーツを表示して [ダイアログを表示 !] のリンクをクリックすると、以下の通り表示され、以下で [新しいプロジェクトを追加] ボタンを押すと、ちゃんと Projects リストにもデータが登録 (新規追加) されます。

 

Comments (0)

Skip to main content