Xpages Typeahead的奇怪行为-搜索字符串随结果一起返回
抱歉,时间太长了。我正在玩一个有着奇特字体的游戏,我遇到了一个我无法解释的问题。我已经找到了一个修复程序,但是这个修复程序没有意义,所以我想知道是否有人可以看看我的示例并解释发生了什么,以及它是否是某种bug?我剥离了大部分功能,提供了一个简单的示例来演示 场景:我有一个文本框,前面有漂亮的字体。除此之外,我还有一个按钮将新找到的值附加到第二个字段中。我使用第二个字段驱动一个repeat控件,该控件显示迄今为止选择的所有值。代码如下 结果:要进行测试,请在字段中键入“ab”,然后选择任何选项,然后单击“添加”链接。重复显示(,abcd)如您所料。测试2,重复该过程两次。重复将显示(、abcd、ab、abcd)。出于某种原因,“ab”被添加到第二个字段中。第三个测试类型ab,选择一个选项,添加。键入“bc”,选择一个选项,然后添加。键入cd,但不要选择选项,而是单击“保存”按钮。然后重复显示(、abcd、bc、abce、cd)。我根本无法解释 解决方法:要使其正常工作,我可以将链接的刷新类型从部分更改为完全。我不知道这为什么会起作用,但确实如此。我不知道我是否真的想那样做,但如果我必须这样做,我会的。这是一个相当复杂的表单,我宁愿不做一个完整的刷新,除非我不得不这样做 代码:下面是一个简化的xpage,演示了问题:Xpages Typeahead的奇怪行为-搜索字符串随结果一起返回,xpages,Xpages,抱歉,时间太长了。我正在玩一个有着奇特字体的游戏,我遇到了一个我无法解释的问题。我已经找到了一个修复程序,但是这个修复程序没有意义,所以我想知道是否有人可以看看我的示例并解释发生了什么,以及它是否是某种bug?我剥离了大部分功能,提供了一个简单的示例来演示 场景:我有一个文本框,前面有漂亮的字体。除此之外,我还有一个按钮将新找到的值附加到第二个字段中。我使用第二个字段驱动一个repeat控件,该控件显示迄今为止选择的所有值。代码如下 结果:要进行测试,请在字段中键入“ab”,然后选择任何选项,然
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Test">
</xp:dominoDocument>
</xp:this.data>
<xp:panel id="mainPanel">
<xp:button value="Save" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:saveDocument var="document1"></xp:saveDocument>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:inputText id="objName1" value="#{document1.objName}">
<xp:typeAhead mode="full" minChars="2" valueMarkup="true"
var="searchValue" id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript: //In here I usually do some searching to find a result set, but for the purposes of a test, let's just do an array
var mapResults:java.util.TreeMap = new java.util.TreeMap();
mapResults.put("abcd", "abcd");
mapResults.put("abce", "abce");
mapResults.put("abcf", "abcf");
mapResults.put("abcg", "abcg");
mapResults.put("abch", "abch");
mapResults.put("abci", "abci");
//Now format the results
var returnList = "<ul>";
//All results are in the TreeMap and are sorted. Now add them to the output
var iter:Iterator = mapResults.entrySet().iterator();
while (iter.hasNext()) {
var nextEntry = iter.next();
returnList += "<li>" + nextEntry.getValue() +"</li>";
}
//Lastly, close off the UL tag and return
returnList += "</ul>";
return returnList;}]]></xp:this.valueList>
</xp:typeAhead>
</xp:inputText>
<xp:link escape="true" text="Add Another Object" id="link1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" id="eventHandler1" refreshId="mainPanel">
<xp:this.action><![CDATA[#{javascript:var currentVals = document1.getItemValueArray("addObjName");
//check for null value in first item in array - happens
//if we clear the array from the 'cross' buttons in the repeat
if (currentVals[0] == null) {
currentVals = new Array("");
}
//get the value from the object name field and whack it on the end
var newValue = getComponent("objName1").getValue();
//Put the value into a test field so we can prove that the value wasn't added below
document1.replaceItemValue("test1", newValue);
//Now add it to the field - where is the search text coming from?
currentVals.push(newValue);
document1.replaceItemValue("addObjName", currentVals);
getComponent("objName1").setValue("");
}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
<xp:repeat id="repeat1" rows="30" var="rowData" indexVar="index"
repeatControls="false">
<xp:this.value><![CDATA[#{javascript:document1.getItemValueArray("addObjName")}]]></xp:this.value>
<xp:panel tagName="div">
<xp:link escape="true" id="link2" title="Remove from list">
<xp:image url="/vwicn081.gif" id="image1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="mainPanel" id="eventHandler2">
<xp:this.action><![CDATA[#{javascript://remove an entry (string) from a list of strings (thanks to Mark Leusink)
Array.prototype.removeEntry = function( entry:String ) {
if ( @IsNotMember(entry, this)) {
return this;
}
var res = @Trim( @Replace(this, entry, "") );
return (typeof res == "string" ? (res.length==0 ? [] : [res]) : res);
}
var oldArray:Array = document1.getItemValueArray("addObjName");
var myArray = oldArray.removeEntry(oldArray[index]);
document1.replaceItemValue("addObjName", myArray);
}]]></xp:this.action>
</xp:eventHandler>
</xp:image>
</xp:link>
<xp:text escape="true" id="computedField1" value="#{javascript:rowData}">
</xp:text>
</xp:panel>
</xp:repeat>
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:"and here is what was added in the link:"}]]></xp:this.value>
</xp:text>
<xp:text escape="true" id="computedField3" value="#{document1.test1}">
</xp:text>
</xp:panel>
</xp:view>
有人要吗?有没有一个合乎逻辑的解释,或者我应该只是利用我的工作,停止学究
更新
使用上面的XPage,我还可以复制以下场景:
步骤1:在字段中键入“abc”,从选项中选择“abcd”,单击“添加”链接。一切都好
第2步:键入'ab'然后等待,然后键入'c',然后选择'abce'。再加一次。这增加了ab、abc、abce
第三步:输入ab然后等待,然后输入c,然后不要选择,而是点击Save。这将添加ab、abc-即使尚未单击链接将值添加到第二个字段
步骤4:键入ab,等待,键入c,选择“abcf”,然后单击添加。这次只添加了abcf
我试图将这一点与下面斯文的答案相协调。部分更新有效,所以我知道他是对的。在上面的步骤2中,我认为typeahead代码执行了两次,每次都触发链接的onClick事件,最后链接的onClick事件正在运行。步骤3中类似的事情-在该示例中根本没有单击链接,但onClick代码仍在运行。在步骤4中,保存之后,typeahead将执行两次,但这次它没有执行onClick代码
现在我想我明白了,即使我不喜欢它。正如Sven所说,$$xspsubmitid标识了上次提交操作中向服务器提交数据的元素。因此,在本例中,它会记住以前的提交状态,并重复该状态-因此,当您在普通保存后立即执行此操作时,您不会得到任何额外的代码,但当您在链接中的事件后执行此操作时,它会以与链接相同的方式提交页面-使用onClick代码完成
这可能是一个原因,为什么这样做是一件好事,但我的头受伤了,问题解决了!谢谢斯文 是您的typeahead更新字段/数组的值。在输入框中键入第二个或多个字符时,输入框中的当前数据将发送到服务器,从而更新文档中的值。单击链接时,会再次添加该值 编辑: 您可以通过将typeahead的模式更改为“部分”来解决此问题 编辑2: typeahed的刷新模式之间的区别在于数据发送到服务器的方式:在完全刷新的情况下,数据通过POST请求发送,在部分刷新的情况下,数据作为GET请求发送 让我们看看不同的HTTP请求: 1.)部分模式 2.)全模式 正如您在两张图片中看到的,在完全模式下,有更多的“字段”发送到服务器。最有趣的是$$xspsubmitid:目前它是空的。但是,一旦我们单击链接,该字段将填充链接的id: $$xspsubmitid标识将数据提交到服务器的元素。在这种情况下,服务器处理链接的代码 现在全模式下的typeahead出现了问题:
正如您所看到的,$$xspsubmitid总是添加到POST请求中,这就是为什么服务器会对每个typeahead请求执行链接的单击事件。谢谢Sven,但我认为这对我来说没有意义。typeAhead位于字段“objName”的控件上,但该值正在添加到用于驱动repeat控件的字段“addObjName”。那里唯一可以向addObjName字段添加任何内容的代码是链接的onClick,但是如果您查看我的测试中的步骤3,保存文档似乎就是将objName字段中的文本放在那里。我一定是遗漏了什么。我确实需要理解完全和部分的区别