9

情况:

我正在制作一个必须使用 ui-select 的 Angular 应用程序:在用户信息页面中,在选择中必须可以选择一个或多个标签。它几乎可以工作,除了我在获取和显示预先存在的标签时遇到问题。

编码:

看法:

<ui-select multiple ng-model="info_data.tags" theme="bootstrap" ng-disabled="disabled">

  <ui-select-match placeholder="Select tag...">{{$item.name}} </ui-select-match>

  <ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">

    {{tag.name}}

  </ui-select-choices>

</ui-select>

<p>Selected: {{info_data.tags}}</p>

控制器:

$http({

    url: base_url + 'main/db_get_all_tags',
    method: "POST",

 }).success(function (data) {

    $scope.all_tags = data;

});

$scope.show_info = function() {

    var result_info = DbService.get_info( $stateParams.db_data_id );

    result_info.then( function( data )
    {
        $scope.info_data = data;

    });

};

尝试 1:

它发生了一个非常奇怪的行为。我在用户的信息页面中看不到标签,甚至在 ui-select 中也看不到。除非刷新 5/6 次,否则它会突然神奇地工作,在用户信息页面和 ui-select 中显示标签。在这两种情况下,无论是否工作,我都会收到几条相同类型的错误消息:

无法读取未定义的属性“长度”。

尝试 2:

为了解决这个问题,我在控制器中添加了这段代码:

$scope.info_data = { tags: [] };
$scope. all_tags = [];

而且我不再收到任何错误消息。该应用程序很稳定,我可以在用户信息页面中看到正确的标签。唯一的问题是标签不再在 ui-select 中加载。

如果我选择一个新标签,那么它可以正常工作,但我会丢失预先存在的标签。

问题):

如何使 ui-select 正常工作?(目前是v0.8.3) 有冲突的问题吗?

我怎样才能正确地从服务器调用预先存在的数据?

非常感谢!

4

3 回答 3

41

您没有特别描述您看到的错误,所以我不知道以下内容是否有帮助..

我最初在使用 ui-select 演示代码作为示例时遇到了问题,因为他们使用的是propsFilter过滤器,这是他们为演示编写的自定义过滤器:

<ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">

我假设您没有在代码中包含此过滤器,这可能是您遇到问题的原因。您可以使用 Angular 的普通过滤器来解决它:

<ui-select-choices repeat="tag in all_tags | filter: {name: $select.search}">

或者,如果您有多个要过滤的属性,您可以编写 propsFilter 过滤器来过滤 OR 而不是 AND。如果您使用“过滤器”过滤多个属性,它将尝试匹配所有属性的搜索值。

app.filter('propsFilter', function() {
  return function(items, props) {
            var out = [];
                if (angular.isArray(items)) {
                  items.forEach(function(item) {
                        var itemMatches = false;

                        var keys = Object.keys(props);
                        for (var i = 0; i < keys.length; i++) {
                              var prop = keys[i];
                              var text = props[prop].toLowerCase();
                              if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                                    itemMatches = true;
                                    break;
                                  }
                            }

                            if (itemMatches) {
                              out.push(item);
                            }
                      });
                } else {
                  // Let the output be the input untouched
                      out = items;
                }

                return out;
          };
    });

你可以在这里看到带有过滤器的提交: https ://github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1

虽然如果您有一些特定的过滤要求,我建议您编写自己的过滤器以确保最佳性能。

于 2014-11-16T14:57:03.853 回答
3

我不知道在 Select2#4.0 之前的情况如何,但如果没有它,使用它真的不是那么难angular-ui-select(而且它的依赖少了一个)

只需包含select2在您的凉亭依赖项中并link在指令中的函数中使用它:

.directive('someDirective', function() {
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            element.find('.your-select2').select2({
                theme: 'classic',
                placeholder: 'Select a placeholder...',
                allowClear: true,
                data: [{ id: 'New', text: 'New'}]...
            });
        },
    };
})

和你的 HTML:

<select class="your-select2" ng-model="a.model.field"></select>

如果需要,您还可以通过服务从控制器加载data,然后只需使用scope设置它!

我在尝试使用时这么说,angular-ui-select因为我认为“嘿,它是 Angular,你必须为它使用插件!”,但情况并非总是如此 :)。另外,我发现文档不是很有帮助(叫我懒惰,但是嘿)

于 2015-07-23T20:23:04.420 回答
0

我稍微优化了 propsFilter。它在做

props[prop].toLowerCase();

在 items 迭代中,但这实际上只需要评估我们拥有的属性的次数。目前已对其进行了评估items count * props count

所以最终优化后的代码是这样的:

app.filter('casinoPropsFilter', function() {
    return function(items, props) {
        var out = [];

        if (angular.isArray(items)) {
            var keys = Object.keys(props);
            var propCache = {};

            for (var i = 0; i < keys.length; i++) {
                var prop = keys[i];
                var text = props[prop].toLowerCase();
                propCache[props[prop]] = text;
            }

            items.forEach(function(item) {
                var itemMatches = false;

                for (var i = 0; i < keys.length; i++) {
                    var prop = keys[i];
                    var text = propCache[props[prop]];
                    if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                        itemMatches = true;
                        break;
                    }
                }

                if (itemMatches) {
                    out.push(item);
                }
            });
        } else {
            // Let the output be the input untouched
            out = items;
        }

        return out;
    };
});    

于 2019-08-29T15:16:31.500 回答