2010-07-21 61 views
11

我有很多麻烦,使jQuery的自动填充小工具为我工作。我正在使用来自服务器的键/值对列表。jQuery UI自动完成与混合文本/ ID搜索

我有以下要求:

如果用户从窗口小部件选择一个值,我想ID传递给服务器。

如果用户没有选择一个值并输入原始文本,或者修改了一个已经被选中的值,我想要清除ID字段,并且只是将原始文本发送到服务器。

假设someAjaxFunction返回自动填充小部件期望的对象数组:{label:label, value:key}

起初我设置自动完成构件像这样:

$(input).autocomplete({ 
    source: sourceFunction, 
    minLength: 1 
}); 

改变选择,甚至通过将鼠标悬停在项目中的一个改变了$(输入)参考下面的键文本框中的文本,而不是标签。从用户交互的角度来看,这是非常不可取的 - 事实上,我正在研究这个问题的原因是因为我正在构建的站点的用户一直对他们输入的文本感到困惑,似乎它们变成了随机数字!

我添加了一个隐藏字段下的文本框中并实施的select()和焦点()事件,以掩饰,像这样的ID:

$(input).autocomplete({ 
    source: sourceFunction, 
    minLength: 1 
    focus: function(event, ui) { 
     $(idField).val(ui.item.value); 
     $(this).val(ui.item.label); 
     return false; 
    }, 
    select: function(event, ui) { 
     $(idField).val(ui.item.value); 
     $(this).val(ui.item.label); 
     return false; 
    }, 
    minLength: 1 
}); 

这种运作良好,当用户被粘到由自动完成下拉菜单提供的脚本。该ID隐藏并正确提交给服务器。不幸的是,如果用户想要在框中输入一些自由格式的文本并根据该值进行搜索,则ID字段不会重置,并且之前选择的ID将被提交给服务器。这也相当混乱。

jQuery UI自动完成文档列出change事件,并指出ui参数的item属性将设置为所选项目。我想我可以重置按键上隐藏的ID字段,并重新填充ID如果自动完成更改。不幸的是,除了按键事件捕获了一大堆按键,不应该重置ID,事件中的事件(这是管理文本框中的文本所必需的)中的语句阻止change事件具有UI .item正确分配。

所以现在我被卡住了 - 我真的不知道还有什么我可以尝试使小部件支持功能,它似乎应该默认支持。要么这个过程比它本该更复杂,要么我错过了一些非常明显的东西。我挑选了所有可用的事件和所有的例子,并且空手而归。事实上,即使jQuery UI页面上的“自定义数据和显示”示例也会遇到这个问题。

我可以在服务器端添加一些黑客来掩盖这一点,但我真的希望能够在客户端级别做到这一点。

我还希望坚持jQuery UI自动填充小部件,而不是切换到另一个。

+0

对不起,我可以澄清一些事情吗?至少有一个问题是,如果用户输入具有相应ID的值,或者如果用户没有对应的值时输入的任何内容,则希望ID框填充* *相关的​​ID - 正确/不正确的? – Stephen 2010-07-27 13:49:39

+0

那么,如果文本框中的文本被设置为与自动完成提供的选项不对应的内容,我只希望隐藏的ID字段为空。 – Shabbyrobe 2010-07-27 14:27:37

回答

2

我在做自动完成的方式是创建一个包含输入的容器div。当我选择一个元素时,我将一个包含span的链接添加到容器中,然后隐藏输入框。

链接和跨度的样式使它看起来像一个按钮,带有一个X,并具有一个单击事件处理程序以从DOM中移除条目,清除隐藏的字段,并在单击时重新显示输入框。所以,当一个项目被选中:

<div class="container"> 
    <a href="#"><span>Selected Item</span></a> 
    <input id="myautocomplete" type="text" /> 
    <input type="hidden" name="myvalue" value="1" /> 
    </div> 

当未选择一个项目:

<div class="container"> 
    <input id="myautocomplete" name="myautocomplete" type="text" /> 
    <input id="myvalue" name="myvalue" type="hidden" value="" /> 
    </div> 

这样,你要么被迫选择一个项目,或者你输入自由格式文本。在后端,如果带有'myvalue'键的请求参数为空,那么您应该使用'myautocomplete'键来查看请求参数。

+0

另外,在jQuery UI自动完成的选择处理程序中,每次选择一个项目时,都可以创建一个具有相同名称的隐藏字段,因此如果选择多个国家/地区,请将隐藏字段的名称属性设置为'countries'。如果您单击某个条目以将其删除,则会删除相关的隐藏字段。在服务器端,您最终会检索必须拆分并转换为整数/长整型数组的ID的逗号分隔列表。 – jamiebarrow 2010-07-27 13:47:20

+0

这是一个很好的建议,在没有任何简单的情况下,这就是我要去的方式。理想情况下,我更喜欢在jQuery UI小部件上构建更少的东西 - 在我看来,小部件应该支持我想要做的或多或少的开箱即用功能。 – Shabbyrobe 2010-07-27 14:30:14

+0

嗯,我一直负责类似的东西,所以我也在寻找如何做到这一点的建议:)很高兴我的建议帮助! 另一件事是,如果有人使用相同的页面进行创建和编辑 - 编辑时重新加载页面,则必须重新创建隐藏字段中值的所有跨度等。目前我只是在服务器端做这件事。唯一的问题是,像现在使用的类的东西现在必须保持在前端代码和后端代码...我不喜欢它,但它的工作原理。 – jamiebarrow 2010-07-28 08:40:19

1

当我想你有以下字段设置:

<div> 
    <input type="text" name="visible" class="autocomplete-reference" /> 
    <input type="hidden" name="hidden" /> 
</div> 

您需要初始化以下JS(它的工作原理与jQuery 1.5.2):

$(document).ready(function() { 
    $('.autocomplete-reference').each(function() { 
     $(this).keydown(function(e){ 
      /* 
      * this will reset hidden id reference on each visible field manual change 
      * we have to bind it on keydown because we want to recognize event of submiting form by enter after autocomplete set 
      */ 
      if (e.keyCode != 13) { 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(''); 
       }); 
      } 
     }); 
     $(this).autocomplete({ 
      minLength: 1, 
      /* you can set appending of autocomplete menu into some container to set css contextually 
      appendTo: '#someElem',*/ 
      source: sourceFunction, 
      search:function (event, ui) { 
       //TODO ...spinner init... 
      }, 
      open:function (event, ui) { 
       /* you can grab autocomplete menu widget by this to manipulate some recognizing id, etc.. 
       * $(this).autocomplete('widget') 
       */ 
       //TODO ..stop spinner ... 
       $(this).keydown(function(e){ 
        /* this is important for live reference updates while arrow keys changes */ 
        if (e.keyCode == 37 || e.keyCode == 39) { 
         $($(this).data('autocomplete').menu.active).find('a').trigger('click'); 
        } 
       }); 
      }, 
      focus: function(event, ui) { 
       /* here we'll map our data object onto both fields */ 
       $(this).val(ui.item.label); 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(ui.item.key); 
       }); 
      }, 
      select: function(event, ui) { 
       /* here we'll map our data object onto both fields */ 
       $(this).val(ui.item.label); 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(ui.item.key); 
       }); 
      }, 
      close: function(event, ui) { 
       //TODO ..stop spinner ... 
      } 
     }); 
    }); 
}); 

这是非常好的,有一些服务器端验证,可以将精确的:可见的字段值转换为引用,以便快速打字。

0

虽然它的一个老问题,我的方法可以帮助。

.change事件中,您可以使用循环从源列表中搜索带有值的文本框值。

转到更多的细节:这里是在Ajax源列表中,但锻炼是类似的。 Search a text In Jquery AutoComplete Ui

这件事就一直困扰了我很多次,最终现在我理解了它:)

0

您可以使用event.preventDefault

通过ui.item.label收集你选择的值或ui.item.value并获取所需的值并将其设置为相同的文本框。

var idNameCombo = ui.item.label; 
      event.preventDefault(); 
      $("#mID").val(idNameCombo.split(",")[0].trim());