Typeahead以查询开头的结果排名更高

时间:2014-11-12 18:14:19

标签: javascript angularjs

我正在使用AngulaJS typeahead指令,如下所示:

typeahead="elements.name for elements in someObject.elements | filter:{name:$viewValue} | orderBy:'name'

$viewValue'foo',输出如下所示,按照确切的顺序:

foo 首先出现 在 foo 之后去了一个吧 bar出现在 foo 之前 酒吧后面有 foo foo 吧很棒

我希望从查询排名更高的结果开始,如下所示:

栏后,

foo 来了 foo 吧真棒 foo 首先出现 在 foo 之后去了一个吧 bar出现在 foo

之前

但我认为没有办法干净利落地做到这一点。

我也尝试了这个:

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

......使用它如下:

typeahead="elements.name for elements in someObject.elements | filter:{name:$viewValue}:startsWith | orderBy:'name'

结果如下:

栏后,

foo 来了 foo 吧很棒

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

您需要更改orderBy,而不是过滤器。也许在orderBy上执行函数而不是属性会达到预期的效果。

可能类似

$scope.typeAheadModel = '';
$scope.orderByPriority = function (element) {
    return element.name.indexOf($scope.typeAheadModel);
}

在您的HTML中,在您的输入中添加ng-model

ng-model="typeAheadModel" typeahead="element.name for element in someObject.elements | filter:{name:$viewValue} | orderBy:orderByPriority

修改

这是plunkr,由于某种原因,当你输入“f”时它没有正确地执行它,但是一旦你输入“fo”它就会正确地命令它。不知道为什么。

答案 1 :(得分:1)

我尝试过Ben的方法,这在大多数情况下可能都是正确的,但对我来说它起作用是因为我有递归ng-includes而不能使用ng-model。

以下是我解决问题的方法(我承认,它有点像黑客,但我称之为干净的黑客):

我故意滥用以下过滤器,以便在订购之前保存viewValue以及在我的queryObj中将过滤器应用于typeaheadService的属性。我也用它来过滤选择的属性。

app.filter('typeaheadFilter', ['typeaheadService', function (typeaheadService) {
    return function (input, queryObj) {
        var key = Object.keys(queryObj)[0],
            query = queryObj[key];

        typeaheadService.setQueryObject(queryObj); // called once, when the viewValue changes

        if (!query) {
            return input;
        }
        var result = [];

        angular.forEach(input, function (object) {
            if (object[key].toLowerCase().indexOf(query.toLowerCase()) !== -1) {
                result.push(object);
            }
        });
        return result;
    };
}]);

以下是typeaheadService的外观(此服务用于设置和获取所有类型的查询对象):

app.factory('typeaheadService', [
    function () {
        var typeaheadQueryObj;
        return {
            getQueryObject: function () {
                return typeaheadQueryObj;
            },
            setQueryObject: function (queryObj) {
                typeaheadQueryObj = queryObj;
            }
        };
    }
]);

在我的MainController我将smartOrder功能添加到$scope

$scope.smartOrder = function (obj) {
    var queryObj = typeaheadService.getQueryObject(),
        key = Object.keys(queryObj)[0],
        query = queryObj[key];
    if (obj[key].toLowerCase().indexOf(query.toLowerCase()) === 0) {
        return ('a' + obj[key]);
    }
    return ('b' + obj[key]);
};

最后,我的typeahead

typeahead="element.name for element in elements | typeaheadFilter:{name:$viewValue} | orderBy:smartOrder | limitTo:dropdownMenuLimit"

答案 2 :(得分:0)

Bens方法也不错,它对我很有用,但如果你的列表中包含大写,那就有问题了。

所以你必须转换两个端点:

$scope.typeAheadModel = '';

$scope.orderByPriority = function (element) {
    var lower_model = $scope.typeAheadModel.toLowerCase();
    var lower_name = element.name.toLowerCase();

    return lower_name.indexOf(lower_model);
}