用复选框重复控制? [英] Repeat control with checkbox?

查看:21
本文介绍了用复选框重复控制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示视图的重复控件.我现在想要包含一个复选框,以便我可以对选定的文档执行操作.添加复选框没有问题,但是如何检查复选框是否被选中,然后转到该行的关联文档?

I have a repeat control which displays a view. I now want to include a checkbox, so that I can perform actions on the selected documents. I have no problem adding the check box, but how can I check if the checkbox is checked then get to the associated document for that row?

我的想法是:

  1. 让复选框更改事件从数组范围变量中添加或删除文档的 UNID.然后只需对该数组中的文档执行操作.

  1. Have the check box change event add or remove the document's UNID from a array scope variable. Then just perform actions on documents in that array.

忘记复选框,只弹出一个列表框,让用户从中选择.

Forget the checkbox and just popup a list box, to allow the user to select from that.

但是有没有更简单的方法?

But is there an easier way?

推荐答案

为了获得最大的灵活性,最好不要将我们的用户界面组件直接绑定到数据;相反,如果我们引入一个中间的数据模型"层(通常,一个描述真实世界对象/人/过程的数据代表,而不是在文档"中思考,这些最终只是证明这些真实的证据-世界上的东西存在),我们的 UI 代码变得非常干净、易于理解和易于维护.当我们继续在文档中思考时,它还可以更轻松地引入那些难以实现的功能.

For maximum flexibility, it's best to not bind our user interface components directly to data; rather, if we introduce a middle "data model" layer (typically, one that describes the real-world objects / people / processes the data is representative of, rather than thinking in "documents", which are ultimately just evidence that these real-world things exist), our UI code becomes very clean, easy to understand, and easy to maintain. It also makes it much easier to introduce features that are otherwise frustrating to implement when we continue to think in documents.

例如,假设我们使用 扩展库 中的对象数据源来创建任意对象(例如,让我们调用它 pendingRequests) 之后我们可以将重复控件绑定到(而不是直接将其绑定到视图):

Suppose, for instance, that we use the Object Data Source from the Extension Library to create an arbitrary object (for example, let's call it pendingRequests) that we can later bind our repeat control to (instead of binding it directly to the view):

// 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 东西更容易处理的实用函数:

Before proceeding, I should point out that the above example includes two pieces of syntactical candy that aren't native to the platform: recycleAll() and navigateToNext(). Both of these are just utility functions for making the stupid recycle stuff easier to handle:

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;
}

好的,现在回到数据模型......具体来说,这个块:

Okay, now back to the data model... specifically, this block:

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,它为我们提供了一种将复选框绑定到此元数据对象的属性的方法......这意味着用户可以通过复选框切换其值.

So for each view entry, we create a very simple object that has all the pertinent info we want to allow the user to interact with, as well as two extra properties that are there for our own code's convenience: unid, which allows to get back to the document if we need to, and selected, which gives us a way to bind a checkbox to a property of this metadata object... which means the user can toggle its value via the checkbox.

以下是我们如何向用户展示这些数据的基本示例:

So here's a basic example of how we might represent this data to the user:

<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>

repeat 控件中的每个复选框现在都直接绑定到元数据对象的 selected 属性,每个行"代表......它也有一个 unid 属性,因此对与此数据模型对应的实际文档进行操作很简单:

Each checkbox in the repeat control is now bound directly to the selected property of the metadata object each "row" represents... which also has a unid property, so acting on the actual documents that correspond to this data model is simple:

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")...但这也意味着我们可以更新,而不必废弃我们的整个数据源并让它从视图中读回所有内容.

Since our data source is just an array of these metadata objects, we can just loop through each, ask whether the user has toggled the selected property of each, and, if so, get a handle on its corresponding document, modify one or more items, and save it. NOTE: because we're using a data source in this example, it won't reload the back end view data on every event. For performance reasons, this is a Very Good Thing (tm). But it does mean that we have to update the in-memory metadata object to match what we changed on the document (i.e. eachRequest.status = "Approved")... but it also means we can update only that, instead of having to scrap our entire data source and have it read everything back in from the view.

作为奖励,添加全选"按钮之类的东西更简单:

As a bonus, adding something like a "Select All" button is even simpler:

for (var i = 0; i < pendingRequests.length; i++) {
    pendingRequests[i].selected = "1";
}

所以,总而言之,我们有一个内存数据模型,在许多情况下,等效操作将执行得更快,但也允许我们编写更少的代码——以及更易读的代码——来做更有趣的事情.

So, in summary, we have an in-memory data model where, in many cases, equivalent operations will execute more rapidly, but also allows us to write less code -- and more readable code -- to do fancier things.

如果您想实时使用此模式(和/或下载上下文中的所有上述源代码),我已将其永久化此处.

If you want to play with this pattern live (and / or download all of the above source code in context), I've immortalized it here.

这篇关于用复选框重复控制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆