我有一個顯示視圖的重複控制。我現在想包括一個複選框,以便我可以對所選文檔執行操作。添加複選框沒有問題,但是如何檢查複選框是否已選中,然後轉到該行的關聯文檔?用複選框重複控制?
思考我所做的是:
有複選框更改事件添加或從陣列範圍變量刪除文檔的UNID。然後只需對該數組中的文檔執行操作。
忘掉複選框,並彈出一個列表框,允許用戶從中進行選擇。
但是有沒有更簡單的方法?
我有一個顯示視圖的重複控制。我現在想包括一個複選框,以便我可以對所選文檔執行操作。添加複選框沒有問題,但是如何檢查複選框是否已選中,然後轉到該行的關聯文檔?用複選框重複控制?
思考我所做的是:
有複選框更改事件添加或從陣列範圍變量刪除文檔的UNID。然後只需對該數組中的文檔執行操作。
忘掉複選框,並彈出一個列表框,允許用戶從中進行選擇。
但是有沒有更簡單的方法?
爲了獲得最大的靈活性,最好不要將我們的用戶界面組件直接綁定到數據上;相反,如果我們引入一箇中間的「數據模型」層(通常是描述數據所代表的真實世界對象/人/過程的層),而不是在「文檔」中進行思考,世界的東西存在),我們的UI代碼變得非常乾淨,易於理解,並易於維護。當我們繼續在文檔中思考時,它也使得更容易引入那些令人感到沮喪的功能。
假設,比如,我們使用的對象數據源從Extension Library創建任意對象(例如,讓我們叫它pendingRequests
),我們可以把我們的重複控制後綁定到(而不是直接結合它的視圖):
// Create an empty array to return at the end:
var results = [];
// Create a view navigator instance for iterating the view contents:
var pendingView = database.getView("pendingRequests");
var entryNavigator = pendingView.createViewNav();
var eachEntry = entryNavigator.getFirst();
while (eachEntry != null) {
// Add metadata about each entry to result array:
var metaData = eachEntry.getColumnValues();
results.push({
startDate: metaData.get(0).getDateOnly(),
endDate: metaData.get(1).getDateOnly(),
employeeName: metaData.get(2),
status: metaData.get(3),
unid: eachEntry.getUniversalID(),
selected: "0"
});
// In case any column values were Domino objects:
recycleAll(metaData);
// Cruise on to the next:
eachEntry = navigateToNext(entryNavigator, eachEntry);
}
// Final Domino handle cleanup:
recycleAll(entryNavigator, pendingView);
// Return our now populated array:
return results;
在繼續進行之前,我要指出的是,上述實施例包括句法糖果的兩片不是天然到平臺:recycleAll()
和navigateToNext()
。這兩者都是剛剛作出愚蠢的recycle
東西就好辦了實用功能:
recycleAll
* More convenient recycling
*/
function recycleAll() {
for(var i = 0; i < arguments.length; i++) {
var eachObject = arguments[i];
// assume this is a collection
try {
var iterator = eachObject.iterator();
while (iterator.hasNext()) {
recycleAll(iterator.next());
}
} catch (collectionException) {
try {
eachObject.recycle();
} catch (recycleException) {
}
}
}
}
navigateToNext
/*
* Safe way to navigate view entries
*/
function navigateToNext(navigator, currentEntry) {
var nextEntry = null;
try {
nextEntry = navigator.getNext(currentEntry);
} catch (e) {
} finally {
recycleAll(currentEntry);
}
return nextEntry;
}
好了,現在回的數據模型。 ..具體來說,這個塊:
var metaData = eachEntry.getColumnValues();
results.push({
startDate: metaData.get(0).getDateOnly(),
endDate: metaData.get(1).getDateOnly(),
employeeName: metaData.get(2),
status: metaData.get(3),
unid: eachEntry.getUniversalID(),
selected: "0"
});
因此,對於每個視圖條目,我們創建一個非常簡單的對象,其中包含我們希望允許用戶進行交互的所有相關信息,以及兩個用於我們自己的代碼便利性的額外屬性:unid
,其中允許我們回到文件,如果我們需要的話,selected
,它給了我們一種方法來綁定複選框到這個元數據對象的屬性......這意味着用戶可以通過複選框切換其值。
因此,這裏是我們如何可能表示這個數據給用戶一個基本的例子:
<ul style="list-style-type: none;">
<xp:repeat var="vacationRequest" value="#{pendingRequests}">
<li style="margin-bottom:10px;">
<strong>
<xp:checkBox value="#{vacationRequest.selected}" text="#{vacationRequest.startDate} - #{vacationRequest.endDate}"
checkedValue="1" uncheckedValue="0" />
</strong>
<xp:text value="#{vacationRequest.employeeName} (#{vacationRequest.status})" tagName="div" />
</li>
</xp:repeat>
</ul>
在重複控制每個複選框現在直接綁定到元數據的selected
財產對象的每個「行」代表...其中也有unid
屬性,因此作用於對應於這個數據模型的實際文件很簡單:
for (var i = 0; i < pendingRequests.length; i++) {
var eachRequest = pendingRequests[i];
if (eachRequest.selected == "1") {
var requestDataSource = database.getDocumentByUNID(eachRequest.unid);
requestDataSource.replaceItemValue("status", "Approved");
if (requestDataSource.save()) {
// update in-memory metadata:
eachRequest.status = "Approved";
}
}
}
由於我們的數據源只是這些元數據對象的數組,我們就可以通過每個迴路,問用戶是否已經切換了每個項目的selected
屬性,並且如果是,則獲取對其相應文檔的處理,修改一個或多個項目並保存它。 注意:因爲在本例中我們使用的是數據源,所以它不會重新加載每個事件的後端視圖數據。出於性能原因,這是一件很好的事情(tm)。但這確實意味着我們必須更新內存中的元數據對象以匹配我們在文檔上更改的內容(即eachRequest.status = "Approved"
)......但這也意味着我們可以更新只有,而不必刪除我們的整個數據並從視圖中讀取所有內容。
作爲獎勵,增加一些像「全選」按鈕,甚至更簡單:
for (var i = 0; i < pendingRequests.length; i++) {
pendingRequests[i].selected = "1";
}
所以,總的來說,我們有,在內存中的數據模型,其中在許多情況下,相當於操作將執行速度更快,但也使我們能夠編寫更少的代碼和更易讀的代碼,以做更有趣的事情。
如果你想玩這種模式生活(和/或下載所有上述源代碼的上下文),我已永生here。
非常具有說明性的例子;-) 現在,把所有這些都放到Java Beans中,並且你有一個精彩的編碼模式.... ;-) –
Bruce, 我做了一個關於從重複控件中選擇文檔的視頻。我沒有使用複選框,但使用了添加和刪除按鈕,然後執行了一些CSS來突出顯示所選文檔。我確定可以使用與添加/刪除按鈕基本相同的代碼。
基本上,我在內存中創建了一個java.util.ArrayList來存放unid,然後在重複行被點擊時填充該數組。我計算了每行的CSS,如果該數組存在於數組中,我更改背景色以顯示它爲「已選中」。我實際上沒有在選定的單元上顯示任何處理,但由於該數組在範圍內存中,因此幾乎可以做任何您想要的操作。反正視頻演示是在這裏:
http://notesin9.com/index.php/2011/04/01/notesin9-025-selecting-documents-from-a-repeat-control/
與往常一樣,蒂姆的回答是長期的健康,理智,和代碼可維護性你最好的選擇。
在我開始爲所有後端邏輯開始使用Java之前,我還採用了另一種路線。您可以創建一個包含HashMap的頁面加載綁定的dataContext,然後將每個複選框綁定到這個複選框 - 它將爲每個鍵填充true或false,然後您可以遍歷map條目並找到真實的條目是檢查值。
我放在一起簡單的例子,在從地名數據庫列表中翻出,以顯示我的意思:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoView var="names" databaseName="names.nsf" viewName="$NamesFieldLookup"/>
</xp:this.data>
<xp:this.dataContexts>
<xp:dataContext var="checkedNames" value="${javascript: new java.util.HashMap() }"/>
</xp:this.dataContexts>
<xp:div id="refresher">
<xp:repeat value="#{names}" var="name" rows="3">
<xp:this.facets>
<xp:pager xp:key="header" id="pager1" layout="Previous Group Next" />
</xp:this.facets>
<div>
<xp:checkBox value="#{checkedNames[name.$9]}">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="refresher"/>
</xp:checkBox>
<xp:text value="#{name.$9}"/>
</div>
</xp:repeat>
<p><xp:text value="#{checkedNames}"/></p>
</xp:div>
</xp:view>
只是一個小小的評論。將ID添加到這些複選框。否則它表現奇怪(至少在8.5.3)。它觸發了我的頁面上的任何點擊。 –
好的建議 - 我已經養成了將ID放在任何具有與之關聯的eventHandler的任何事情上的習慣(除了視圖根,我猜)。 –
(HTTP [從外訪問控制重複組件內的值]:// xcellerant達網絡/ 2013/07 /第29 /訪問重複基部件從 - 外/)。看看鏈接,它會給出一些相當不錯的提示。它在SSJS中完成,但它很難將其擴展到客戶端JavaScript。 – Naveen
有一個更簡單的方法。今天下午我會發佈一個示例語法。 –