【问题标题】:XPages typeahead how to send value of a combo box filter to the serverXPages typeahead 如何将组合框过滤器的值发送到服务器
【发布时间】:2014-08-13 17:46:44
【问题描述】:

我有一个具有简单搜索功能的 XPage。
简单搜索由一个组合框组成,该组合框表示包含要搜索的信息的项目的名称,以及一个文本框输入字段,用户可以在其中输入要搜索的值。

“过滤器”组合框包含“RecordID”、“请求者”、“受让人”等内容。

当用户选择过滤器并键入要搜索的词并按回车键时,将在服务器上执行搜索并正确返回结果。例如,如果用户选择“RecordID”并输入“ABCD”并按回车键,则将返回 RecordID 字段中包含“ABCD”的所有结果记录。如果用户选择“请求者”并输入“Joe Smith”,则返回请求者字段中包含“Joe Smith”的所有记录。这很好用。

我的问题是当我尝试将预先输入添加到值字段时。预输入有效,但仅过滤组合框的 LAST SUBMITTED 值。示例:如果用户选择“RecordID”并且最后一次搜索是使用“RecordID”执行的,那么在他们输入信息时,预输入将正确过滤 RecordID 结果。如果用户将过滤器更改为“请求者”并开始输入名称,则不会返回结果。如果他们按 Enter 键并根据 Requestor 返回结果,然后清除 value 字段并开始输入另一个 Requestor 的名称,则 typeahead 工作正常。

我很确定问题是由于我不知道如何在 typeahead 事件期间访问组合框的值。我的代码如下(使用 println 语句尝试确定组合框的值。.value 属性和 .getValue() 方法都返回组合框的先前提交的值。.getSubmittedValue() 属性是返回 null。

<xp:comboBox
    id="simpleSearchFilter1"
    value="#{XSPrequestSearcher.simpleSearchFilter}">
    <xp:selectItems
        value="#{XSPrequestSearcher.simpleSearchChoices}" />
</xp:comboBox>

<xp:inputText
    id="simpleSearchValue1"
    value="#{XSPrequestSearcher.simpleSearchValue}">
    <xp:typeAhead
        mode="partial"
        valueMarkup="true"
        var="searchfor"
        minChars="3">
        <xp:this.valueList><![CDATA[#{javascript:var obj = getComponent("simpleSearchFilter1");
var value = obj.value;
var gvalue = obj.getValue();
var svalue = obj.getSubmittedValue();

println("***********");
println("simpleSearchValue1.typeahead");
println("\t value: " + value);
println("\t gvalue: " + gvalue);
println("\t svalue: " + svalue);

XSPrequestSearcher.setSimpleSearchFilter(getComponent("simpleSearchFilter1").value);
XSPrequestSearcher.getTypeaheadChoicesSimple(searchfor); }]]></xp:this.valueList>
    </xp:typeAhead>
    <xp:eventHandler
        event="onchange"
        submit="true"
        refreshMode="partial"
        refreshId="#{compositeData.partialRefreshTargetID}">
        <xp:this.script>
            <xp:executeClientScript>
                <xp:this.script><![CDATA[return !isBlank("#{id:simpleSearchValue1}");]]></xp:this.script>
            </xp:executeClientScript>
        </xp:this.script>
        <xp:this.action><![CDATA[#{javascript:XSPrequestSearcher.setSimpleSearchFilter(getComponent("simpleSearchFilter1").value);}]]></xp:this.action>
    </xp:eventHandler>
</xp:inputText>

【问题讨论】:

  • 是否可以将 simpleSearchFilter1 绑定到作用域变量,并引用作用域变量?或者,如果它绑定到 java bean,则引用 bean 而不是 getComponent。不知道这是否会有所作为,但值得一试。
  • 绑定到 Bean 上的变量属性。我还在作用域变量上进行了尝试。问题是它不会更新,除非我为我真的不想做的 on change 事件设置提交。
  • 很确定你试过了。也许试试这个,在 onClick 事件中,让客户端代码使用 XSP.PartialRefreshPost 将字段的当前值写回服务器,并将其设置为范围变量或您可以访问它的地方。
  • 问题是,如果您不将所选项目发送回服务器,您的预输入将永远不会知道用户选择了哪个项目。因此,在用户开始在您的搜索字段中输入之前,您必须通过 Ajax 将选择发送到服务器并将过滤后的项目返回给客户端。将 Serdars 解决方案用于最小的 onchange 事件,但我确定您必须刷新搜索字段或至少刷新输入。

标签: javascript combobox xpages client-side typeahead


【解决方案1】:

当您更改组合框的值时,它不会将其值提交给服务器。由于预先输入中的部分刷新在您的输入组件周围本地工作,因此它不知道组合框的客户端值。

所以有两种选择。首先,您可以通过在组合框内添加一个简单的 eventHandler 来提交每次更改的组合框值:

<xp:eventHandler
    event="onchange"
    submit="true"
    refreshMode="norefresh" 
    disableValidators="true">
</xp:eventHandler>

每当用户更改其值时,这将进行一次简短的 AJAX 调用。在这种情况下,它不需要刷新任何内容或验证字段。

更新:

上述方法会造成 UI 延迟,使用此 snippet 无法按照您在评论中的建议工作。因为部分刷新操作是异步操作,所以当你启动 typeahead 时,它不会等待部分刷新操作。

但是稍微修改一下 sn-p 就可以了。这里的问题是,如果没有 searchFilter,searchValue 对我们没有任何意义。因此,我寻找了一种同时提交这两种信息的方法。这可以通过与 sn-p 相同的方法来实现。

首先,我为typeAhead 提供了id。这很重要,尤其是当您想在同一页面上使用多个 typeAhead 时。

<xp:typeAhead
    id="simpleSearch"
    mode="partial"
..... other attributes ....
</xp:typeAhead>

现在我们将在 Ajax 请求中注入一些 CSJS,特别是针对 typeahead 请求。

<xp:eventHandler
    event="onClientLoad"
    submit="false">
    <xp:this.script><![CDATA[ 
dojo.addOnLoad( function(){

/*** hijacking xhr request ***/
if( !dojo._xhr )
  dojo._xhr = dojo.xhr;

dojo.xhr = function(){
  try{
     var args = arguments[1];
     if( args['content'] ){
        var content = args['content'];
           if( content['$$ajaxmode'] ){
              if( content['$$ajaxmode'] == "typeahead" ){
                    // Paranoid check for multiple typeahead:
                  if(content['$$ajaxid'] == "#{id:simpleSearch}") {
                    var filterType=dojo.byId("#{id:simpleSearchFilter1}").value;
                    content['$$value']=filterType+":"+content['$$value'];
                  }
              }
         }
     }
  }catch(e){}
  dojo._xhr( arguments[0], arguments[1], arguments[2] );
}
});]]></xp:this.script>
</xp:eventHandler>

在这里,我们基本上检查了每个 typeahead 请求。如果某个 typeahead 源自我们的 typeahead,我们在提交的 searchfor 值前面添加过滤器类型。因此,我们的搜索值将会改变。您需要相应地更改 typeAhead 值列表函数:

var searchFilter=@Left(searchfor, ":");
var searchValue=@Right(searchfor, ":");
// Use searchFilter and searchValue to generate a value list.

这里有一点小提示。我们正在使用 Ajax 注入。如果我们的页面正在使用类似的注入(例如待机对话框等),则应仔细修改dojo._xhr等变量名称。

【讨论】:

  • 使用 eventHandler 会导致 UI 延迟。使用 sn-p 和 partialRefreshPost() 之类的作品 - 在第一个 typeahead 返回之后。随后的结果被过滤。 EX:用户将过滤器设置为“Requestor”并输入“Joh” - 服务器上的 typeahead 过滤器仍然是“RecordID”并且没有找到匹配项,将空字符串返回给浏​​览器。如果用户键入“n”,则服务器过滤器现在是“Requestor”,并找到与“John”匹配的内容。预先输入的结果被发送回浏览器(“John Bigbooté”、“John O'Connor”、“John Small Berries”、“John Whorfin”、“John Yaya”等)
  • 我想我知道问题所在。由于部分刷新是异步操作,因此它会在提交结束前开始预先输入。我会考虑一个更好的解决方案。
  • @spanky762 我添加了一个 hacky 解决方案。我希望它有所帮助。
【解决方案2】:

我建议您让您的预输入代码与组合框中的任何可能项目一起使用。使用 SSJS 或 Java,您可以构建一个可能的预输入示例的 HashMap,但循环多个集合。它真的很好用。我们在日常工作中有效地使用它。

我在第 24 期节目中对此做了简短的 NotesIn9:http://notesin9.com/index.php/2011/02/11/notesin9-24-fancy-type-ahead-in-xpages/

在那个节目中,如果你输入一个人的姓氏或名字,我前面有一个类型。 (这不是我最好的视频,但你明白这个概念)

所以在您的示例中,您可以使用您的预输入来对抗:RecordID 或请求者或任何其他选择。然后,如果您真的想知道组合框中的内容,您可以在提交时访问它。

效果很好....

【讨论】:

  • 虽然这个答案并没有真正解决如何将组合框中的选定值返回到可用于过滤结果的服务器的问题,但它确实允许我获得预先输入的结果(尽管未过滤)并将它们发送回浏览器客户端。出于这个原因,我投票赞成。
猜你喜欢
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 2021-11-15
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多