XPages事件代码执行两次而不是一次

时间:2013-10-30 17:08:46

标签: xpages

这就是我想要做的事情:

在XPage上我想要一个编辑框控件,当用户按下回车键时,它会调用一些服务器端代码(Java bean或SSJS)。这个主要用例是这个页面将从iPad上运行,并附带一个蓝牙条码扫描器。此扫描仪模拟键盘。用户将点击编辑框。然后,他们将使用扫描仪扫描,条形码将与“输入”键一起输入。需要立即清除编辑框以进行下一次扫描,并且需要处理扫描值。处理将对java bean执行各种后端操作,然后返回要在页面上显示的消息。基本上是其中之一: 1.物品未找到,2。物品可用并已分配,3。物品已经分配,​​但无论如何都可以使用4.物品不可用

我有这方面的代码,整体而言核心代码工作正常。我通常使用onchange事件,但由于我遇到了这个问题,我转到了onkeypress事件。这也是尝试让它在IE中运行。再次,目标只适用于iPad / Safari,但我也希望能够在桌面浏览器上使用它。我目前只在Chome进行测试。

在编辑框的CSJS中我有这段代码:

var e = dojo.fixEvent(thisEvent);
if (e.keyCode == dojo.keys.ENTER) {
return true;
} else {
return false;
}

我的想法是我只想在Enter上调用SSJS。

这是SSJS代码,它清除编辑框,处理值,然后设置一些viewScope变量。

// Get the value off the page and put it in to the key variable
var key:String = getComponent("scanBox").getValue();
// clear the scanbox so it's ready for the next scan.
getComponent("scanBox").setValue("");
//Managed Bean to hold the last scan value - since the scanbox is cleared we do want to show the value
Scan.setLastScan(key);

// Managed Bean to process the item.
AddToJob.processItem(key);

viewScope.put("vsShowAssignPanel", true);
viewScope.put("vsShowMessagePanel", false);

SSJS代码设置为部分更新页面的主要内容。我正在使用bootstrap并尝试刷新页面上的所有内容,除了顶部和底部导航栏。编辑框本身位于部分刷新区域,因为我在扫描后清除了值。

最后这是问题所在:

按钮的SSJS代码正在运行TWICE。不是出于某种原因,但可能有90%的时间。我没有点击两次。我测试的方法是在桌面上使用Chrome,然后在字段中粘贴一个值,然后在键盘上输入一次。

如果我正在尝试扫描并指定带有条形码的项目。它首先运行良好。它更新对象并将字段保存到后端NotesDocument以标记它已分配。只想要我想要的。但第二次是通过命中,它阻止该项目已被分配并给我错误的信息。

经过大量的反复试验后,我非常肯定JSF生命周期中的某些内容导致它运行两次。为什么我不知道。我不知道怎么弄它。

到目前为止,我发现的唯一好的解决方法是在“AddToJob.processItem”方法中。 “AddToJob”是viewScope中的托管bean。在那里我存储并保留最后一个barCode。然后我做一个检查,看看价值是一样的。如果是这样,那么我认为它是在第二次运行并停止处理。

我已经在编辑控件的on change事件中使用了这个基本概念来调用代码多年。但那是在XPages Mobile Controls中,有时事情的确表现得有些不同。我正在尝试重新编写此应用程序以使用Bootstrap而不是XPages Mobile控件。

如果有帮助,下面是编辑控件的完整XML标记。

<xp:inputText id="scanBox" styleClass="newTarget">
<xp:this.attrs>
    <xp:attr name="placeholder" value="Tap to Scan..." />
    <xp:attr name="autocorrect" value="off" />
</xp:this.attrs>
<xp:this.dojoAttributes>
    <xp:dojoAttribute name="autocorrect" value="off" />
</xp:this.dojoAttributes>
<xp:eventHandler event="onkeypress" submit="true" refreshMode="partial" refreshId="mainPanel">
<xp:this.script><![CDATA[var e = dojo.fixEvent(thisEvent);
if (e.keyCode == dojo.keys.ENTER) {
return true;
} else {
return false;
}]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:// Get the value off the page and put it in to the key variable
var key:String = getComponent("scanBox").getValue();
// clear the scanbox so it's ready for the next scan.
getComponent("scanBox").setValue("");

//Managed Bean to hold the last scan value - since the scanbox is cleared we do want to show the value
Scan.setLastScan(key);

// Managed Bean to process the item.
AddToJob.processItem(key);

viewScope.put("vsShowAssignPanel", true);
viewScope.put("vsShowMessagePanel", false);}]]></xp:this.action>
</xp:eventHandler></xp:inputText>

感谢任何信息。非常感谢!!!

3 个答案:

答案 0 :(得分:7)

Enter键是一个特殊键,因为按Enter键也可以提交您当前所在的表单。在这种情况下,您实际上有两个POST请求命中服务器,一个用于部分请求,另一个用于提交表单。

您需要做的是阻止enter键使用event.preventDefaults()调用提交表单。这是更新的CSJS

var e = dojo.fixEvent(thisEvent);
if (e.keyCode == dojo.keys.ENTER) {
    e.preventDefault();
    return true;
} else {
    return false;
}

现在表单将不会提交,但部分刷新将正确启动。

答案 1 :(得分:0)

如果我在这里遗漏了什么,请原谅我,但在我看来,你已经设置了一个不必要的复杂设计。

为什么CSJS或SSJS甚至需要?

意思是,您是否尝试过一些简单的标记和bean来进行处理?

示例标记:

<xp:panel
id="panelbarcode">
<xp:inputText
    id="barcode1"
    value="#{MyBean.barcode}">
    <xp:eventHandler
        event="onchange"
        submit="true"
        refreshMode="partial"
        refreshId="panelbarcode" />
</xp:inputText>
</xp:panel>

示例Bean代码:

public class MyBean implements Serializable {

private static final long serialVersionUID = 8541L;

// Zero-Argument Constructor
public MyBean() {}

public String getBarcode() {
    // give out a barcode here, 
    // or return "" for an empty barcode
    return "";
} 

public void setBarCode(String barcode) { 
    // process the scanned in barcode 
} 
}

(编辑以摆脱愚蠢的“onClick”事件)

答案 2 :(得分:0)

大卫,

不是特定的XPage解决方案,但我必须在Notes客户端中执行此操作 - 其中扫描条形码 - 处理完毕,然后清除字段,然后扫描下一个。操作员不是在客户端(它是一个蓝牙扫描仪)。

我的解决方案并且我承认使用NotesTimer有点令人讨厌 - 通过检查字段内容是否为空或者它是否具有与之前相同的值。为了确保我没有捕获到部分扫描,我做了两次检查,如果值没有改变,那么我就进行了处理。

所以那么 - 你不能使用Javascript计时器并遵循相同的逻辑吗?