我有一个显示视图的重复控制。我现在想包括一个复选框,以便我可以对所选文档执行操作。添加复选框没有问题,但是如何检查复选框是否已选中,然后转到该行的关联文档?用复选框重复控制?
思考我所做的是:
有复选框更改事件添加或从阵列范围变量删除文档的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
有一个更简单的方法。今天下午我会发布一个示例语法。 –