AngularJs UI typeahead 匹配前导字符

Posted

技术标签:

【中文标题】AngularJs UI typeahead 匹配前导字符【英文标题】:AngularJs UI typeahead match on leading characters 【发布时间】:2013-08-28 02:34:00 【问题描述】:

AngularJs UI 中的 typeahead 功能看起来简单而强大,但是我一直在尝试弄清楚如何在前导字符上进行匹配。例如,如果我在输入框中键入“A”,我想查看所有以“A”开头的州,而不是所有名称中包含“A”的州。我一直在寻找几天关于这一点,似乎 Angular 有一个具有“比较器”的自定义过滤器的概念。关于此的文档有一个简单的示例,它没有显示实现比较器的确切语法。

html 看起来像这样:

<div>Selected: <span>selected</span></div>
    <div><input type="text" ng-model="selected" typeahead="name for name in states | filter:selected"></div>

基本的 javascript 是这样的

angular.module('firstChar', ['ui.bootstrap']);

    function TypeaheadCtrl($scope) 
        $scope.selected = undefined;
        $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
    

我这里有个小哥哥http://plnkr.co/edit/LT6pAnS8asnpFEd5e6Ri

因此,简而言之,挑战是让 AngularUI 预先输入以匹配前导字符。

非常感谢您对此提供任何帮助或想法。

【问题讨论】:

【参考方案1】:

归根结底,您的问题并不是真的针对 typeahead 指令,而是更多地与 AngularJS 过滤器的工作方式有关。

在提出可行的解决方案之前,请注意typeahead 指令大量使用了 AngularJS 基础架构($http,promises)和表达式语言。因此,重要的是要意识到states | filter:selected 只不过是一个 AngularJS 表达式。

看看上面的表达式,我们需要找到一种过滤数组的方法,以返回匹配项的列表。 typeahead 指令唯一的特别之处是有一个$viewValue 变量,表示用户在输入框中输入的值。所以我们基本上只需要过滤states数组,返回以$viewValue开头的项目。

有很多方法可以做到这一点,但是由于您提到了过滤器的比较器(请注意,这些仅在 AngularJS 的 1.1.x 版本中引入)您必须定义一个比较器函数,该函数应该决定是否给定一个项目是否应该在结果列表中返回。这样的函数可能如下所示:

$scope.startsWith = function(state, viewValue) 
  return state.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase();
 

定义了用法就很简单了:

typeahead="name for name in states | filter:$viewValue:startsWith"

这里是工作 plunk:http://plnkr.co/edit/WWWEwU4oPxvbN84fmAl0?p=preview

【讨论】:

哇!谢谢!似乎工作完美。给出了 Angular 的概念和链式语法的一个很好的例子。 一个问题......我们如何在startsWith函数中定义“状态”?我意识到它正在遍历状态,但它是如何提出名称/对象“状态”的。我正在尝试在更真实的示例中使用此代码,但它不起作用。 我的问题的答案是示例中的“状态”是用于填充预输入列表的数组中的当前值。我的问题是我正在使用一个对象来填充预先输入的内容,因此我可以获得所选值的“id”。 Angular 遍历对象并将对象的每个成员传递给比较函数以进行字符串比较。 最后,如果你想获得一个 'id' 并显示另一个值,这是语法 '' 谢谢!它真的非常有用保持下去:)【参考方案2】:

自定义过滤器,用于在打字头自动完成框中的前导字符上进行匹配。

(function() 

    // Create global filters using angular.filter() only. Never use local filters inside
    // controllers/services. This enhances testing and reusability.
    function xpTypeaheadFilter() 
          return function(items, props) 

            var out = [];
            
            if (angular.isArray(items)) 

              items.forEach(function(item) 
                
                


                var text = props.toLowerCase();
                var itemLoverCase =item.toLowerCase();
                var substr = itemLoverCase.substr(0, text.length);

                 
                if (substr === text ) 
                    
                     out.push(item);
                     
                
                

              );
             else 
              // Let the output be the input untouched
              out = items;
            
            console.log("out lem", out.length);

            return out;
          ;
    

    // Pass functions into module methods rather than assigning a callback.
    // This helps aid with readability and helps reduced the amount of code "wrapped"
    // inside Angular.
    angular.module('common')
    .filter('xpTypeaheadFilter', xpTypeaheadFilter);
)();
&lt;input type="text" ng-model="vesselName" placeholder="Vessel Name" typeahead="vesselName for vesselName in vesselNames | xpTypeaheadFilter:$viewValue | limitTo:8"  class="form-control form-textbox" &gt;

【讨论】:

【参考方案3】:

我刚刚编辑了标记为已回答的帖子,当列表同时具有 ID 和标题时它可以工作:

<input type="text" ng-model="ledgerstatementModel.Supplier" typeahead="supplier as supplier.Name for supplier in supplierList | filter:Name:$viewValue:startsWith" class="form-control">

在 js 中:

 $scope.startsWith = function (supplier, viewValue) 
        return supplier.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase();
    

【讨论】:

以上是关于AngularJs UI typeahead 匹配前导字符的主要内容,如果未能解决你的问题,请参考以下文章

ui.bootstrap.typeahead:如何将 $http 与 debounce 结合使用

从 Jquery-ui 自动完成到 typeahead.js

Angular UI/bootstrap typeahead 显示“错误:无控制器:ngModel”错误

Twitter Typeahead.js 如何返回字符串中的所有匹配元素

html angular-ui-bootstrap Typeahead的示例用法(https://angular-ui.github.io/bootstrap/)

添加颜色以匹配twitter typeahead中的文本突出显示