文章目錄
- 在列表B中建立一條來源與列表A的記錄
- 回到jQuery部分的工作
- 拆開來看
- 插入和刪除
回顧在本系列第14部分中,我們提到“如何將PreSaveAction()與jQuery配合使用”。PreSaveAction()允許我們在儲存記錄前做一些事情,當時我快速的列了一些在現實情境中可能會用jQuery做的事。我們舉了一個審計跟蹤的例子。當主列表發生變更時,向另一個列表中寫入主列表的變更資訊。最終實現的效果是我們有兩塊體現真實資訊的地方:(1)當前視圖(2)一個關於變更的記錄,展示達到當前視圖所經曆的過程。
在本文中,我打算花一點時間剝開一層洋蔥皮,看一下具體如何?當清單項目被建立,修改或刪除時在另一個列表中寫記錄。
在列表B中建立一條來源與列表A的記錄
有太多的項目中需要我們在列表中插入,編輯,或刪除清單項目,沒準你現在進行的項目中就有類似的需求吧。或許你以前做過訂單處理解決方案,其中訂單產生後我們需要更新庫存資訊。又或許是一個圖書借閱系統,當有人借出一本書時你需要更新該書的狀態。
要給另一個列表更新資訊我們有很多選擇。但如果你是要建立一個條全新的清單項目,就像審計跟蹤例子中需要的那樣,要面臨哪些挑戰呢?顯然,你必要決定什麼資料需要抓取到審計追蹤記錄裡。在主列表中的每一個需要記錄變更的欄,都必須在審計列表中存在對應的欄。
從本例的設計初衷出發,我們會選取主列表中幾乎所有的欄記錄其變更,進行審計。
主列表——FTE(全日制僱員,Full-time Employees)
FTE的審計跟蹤列表
其中的名稱和順序沒必要完全吻合。對於本例來說,欄的對應關係如下:
主列表(顯示名稱| 內部名稱) |
審計列表(顯示名稱| 內部名稱) |
Location | @LocDept |
Location | @Location |
Group | @Group12 |
Group | @Group |
Position | @Positions |
Position | @Position |
Worker | @Title |
Employee | @Title |
Work Shift | @Workshift |
Work Shift | @WorkShift |
FTE | @FTE |
FTE |@FTE |
EffDate | @EffDate |
Effective Date | @EffDate |
Old Location | @Old%5Fx0020%5FLocation |
|
Last Change | @Audit |
|
|
Change Type | @ChangeType |
|
Month | @Month |
|
Year | @Year |
|
From/To | @FromTo |
建立者(Created By) 和 修改者(Modified By) 會由 SharePoint 自動填寫,所以在兩個列表中我們都不考慮這兩個欄位。
注意:兩個列表的定義有以下幾點不同:
- 在主列表中有一些查閱項類型的欄,對應到審計跟蹤列表時變成了單行文本。
- 我在主列表中添加了一個Last Change欄。我們將用於儲存最新一條審計記錄的ID,並顯示其修改時間欄位。這裡與Effective Date不同。
- 在審計列表中,我添加了:
- Change Type:一個選項型的欄(New,Update,Terminate,Resign,Transfer)——當一條清單項目被插入,該值為New;對於編輯,如果Location發生了修改,則該值為Transfer;任何其他的修改都設為Update。如果清單項目被刪除,我們將記錄是有公司解僱的(Terminate)還是有僱員提出辭職的(Resign)。【標註:在這裡做一個記號,將來當我們討論建立一個備用編輯模版時還會提及】
- From/To:選項型的欄(From,To)——用於顯示記錄變更前/後的視圖,即一次修改會建立兩條記錄。
- Month:計算欄,用來取出Effective Date的月份,方便進行排序/分組。[公式: =TEXT([Effective Date],"mm – mmmm")]
- Year:計算欄,用來取出Effective Date的年,方便排序。 [公式:=TEXT([Effective Date],"yyyy")]
FTE 變更審計
回到jQuery部分的工作
這裡的jQuery指令碼也是來自與第14部分(有關變數的建立,請參考第13部分),其中用到了Marc Anderson的SPServices庫:
function PreSaveAction() { var txtChangeType = "Update"; var txtNewName = $("input[name*=$ff1_]").val(); var txtOldName = $("span[id*=_ff9_]").text(); var txtNewPos = $("input[name*=$ff3_]").val(); var txtOldPos = $("span[id*=_ff11_]").text(); var txtNewShift = $("select[name*=$ff4_]").val(); var txtOldShift = $("span[id*=_ff12_]").text(); var txtNewFTE = $("input[name*=$ff5_]").val(); var txtOldFTE = $("span[id*=_ff13_]").text(); var txtNewGrp = $("input[name*=$ff2_]").val(); var txtOldGrp = $("span[id*=_ff10_]").text(); var txtNewLoc = $("input[name*=$ff6_]").val(); var txtOldLoc = $("span[id*=_ff14_]").text(); var txtEffDate = $("input[name*=$ff7_]").val(); if (txtNewLoc != txtOldLoc) txtChangeType = "Transfer"; $().SPServices({ operation: "UpdateListItems", async: false, listName: "FTE Change Audit", updates: "<Batch OnError='Continue' PreCalc='TRUE'>" + "<Method ID='1' Cmd='New'>" + "<Field Name='FromTo'>From</Field>" + "<Field Name='Title'>" + txtOldName + "</Field>" + "<Field Name='Location'>" + txtOldLoc + "</Field>" + "<Field Name='Group'>" + txtOldGrp + "</Field>" + "<Field Name='Position'>" + txtOldPos + "</Field>" + "<Field Name='WorkShift'>" + txtOldShift + "</Field>" + "<Field Name='FTE'>" + txtOldFTE + "</Field>" + "<Field Name='EffDate'>" + txtEffDate + "</Field>" + "<Field Name='ChangeType'>" + txtChangeType + "</Field>" + "</Method>" + "</Batch>", completefunc: function(xData, Status) { } }); $().SPServices({ operation: "UpdateListItems", async: false, listName: "FTE Change Audit", updates: "<Batch OnError='Continue' PreCalc='TRUE'>" + "<Method ID='1' Cmd='New'>" + "<Field Name='FromTo'>To</Field>" + "<Field Name='Title'>" + txtNewName + "</Field>" + "<Field Name='Location'>" + txtNewLoc + "</Field>" + "<Field Name='Group'>" + txtNewGrp + "</Field>" + "<Field Name='Position'>" + txtNewPos + "</Field>" + "<Field Name='WorkShift'>" + txtNewShift + "</Field>" + "<Field Name='FTE'>" + txtNewFTE + "</Field>" + "<Field Name='EffDate'>" + txtEffDate + "</Field>" + "<Field Name='ChangeType'>" + txtChangeType + "</Field>" + "</Method>" + "</Batch>", completefunc: function(xData, Status) { } }); return true; }; </script>拆開來看
假設表單操作按鈕已經被我們改為調用PreSaveAction(),那麼這段指令碼就會把變更儲存至到審計列表。下面是整個過程的慢動作回放:
修改類型
var txtChangeType = "Update";
大多數的變更為Update類型。但是當Location發生修改時,類型就變成了Transfer(不考慮其他欄是否發生了修改...你的情境可能於此不同)。在我們設定所有的變數前,應對該項進行檢查。
var txtNewLoc = $("input[name*=$ff6_]").val(); var txtOldLoc = $("span[id*=_ff14_]").text(); . . . if (txtNewLoc != txtOldLoc) txtChangeType = "Transfer";Effective Date
由於Effective Date的變更只涉及到本身,所以這種情況下From和To兩個變更版本是相同的。
SPServices
現在,我們得到了變更前的“舊”值和變更後的“新”值,接下來直接通過SPServices調用UpdateListItems建立兩條記錄就可以了。在上面的29行到41行,我們告訴函數建立一條新記錄。然後,我們只需載入上CAML把值填入審計列表的相應的欄即可。
或者,我們可以用下面的文法替換updates中使用的CAML:
batchCmd: "New", valuepairs: [["FromTo", "From"], ["Title", txtOldName], ["Location", txtOldLoc], ["Group", txtOldGrp], ["Position", txtOldPos], ["WorkShift", txtOldShift], ["FTE", txtOldFTE], ["EffDate", txtEffDate], ["ChangeType", txtChangeType]],
注意到其中listName是目標列表的顯示名稱:
listName: "FTE Change Audit",
接下來對應FromTo="To"再重複一遍上面的過程。我們就完成了兩條審計追蹤記錄的建立。
插入和刪除
你可以在建立時使用相同的技術,但如果用工作流程來處理“建立項目時”會更容易些。如果你需要我對這兩種方式進行詳細講解的話請發表評論。
我們會在將來講到添加一個備用編輯模版時使用Resign和Terminate變更類型。
下一次:如果你需要在DVWP中從一個關聯的列表更新資料該怎麼辦?在接下來的擴充DVWP系列中,我們會公布謎底。
參考資料
SharePoint:Extending the DVWP - Part 25:Using an Audit Trail by Creating List Items with SPServices