简体   繁体   English

AngularJs:如何让ui-select正常工作?

[英]AngularJs: How make ui-select working properly?

THE SITUATION: 情况:

I am making an angular app where I have to use ui-select: in the user info page, in the select have to be possible to choose one or many tag. 我正在制作一个角度应用,我必须使用ui-select:在用户信息页面中,在选择中必须可以选择一个或多个标签。 It is almost working, except from the fact that i have problems to get and display the pre-existent tags. 它几乎正常工作,除了我有问题得到并显示预先存在的标签。

THE CODE: 代码:

View: 视图:

<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>

Controller: 控制器:

$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;

    });

};

ATTEMPT 1: ATTEMPT 1:

It happens a very strange behavior. 它发生了一种非常奇怪的行为。 I don't see the tags in the info page of the user, and not even in the ui-select. 我没有在用户的信息页面中看到标签,甚至在ui-select中也看不到。 Except if refresh 5/6 times, then suddenly it will magically work, displaying the tags in the user info page and in the ui-select. 除非刷新5/6次,否则突然它会神奇地工作,在用户信息页面和ui-select中显示标签。 In both cases, working and not, i get several error message of the same kind: 在这两种情况下,工作与否,我得到几个相同类型的错误消息:

Cannot read property 'length' of undefined. 无法读取未定义的属性“长度”。

ATTEMPT 2: ATTEMPT 2:

In order to resolve this problem, I have added this code in the controller: 为了解决这个问题,我在控制器中添加了这个代码:

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

And i don't get anymore any error message. 而且我不再收到任何错误消息。 The app is stable and i can see the proper tags in the user info page. 该应用程序是稳定的,我可以在用户信息页面中看到正确的标签。 The only problem is that the tags are not loaded anymore in the ui-select. 唯一的问题是标签不再在ui-select中加载。

If i select a new tag then it works fine, but i loose the pre-existing tags. 如果我选择一个新标签然后它工作正常,但我松开了预先存在的标签。

QUESTION(s): 问题(S):

How can i make ui-select properly working? 如何让ui-select正常工作? (currently v0.8.3) There is a problem of conflict? (目前v0.8.3)存在冲突问题?

How can i properly call pre-existent data from the server? 如何从服务器正确调用预先存在的数据?

Thank you very much! 非常感谢你!

You haven't been particularly descriptive with the errors you're seeing so I don't know if the following will help.. 你没有特别描述你所看到的错误,所以我不知道以下内容是否会有所帮助..

I had a problem originally when using the ui-select demo code as an example because they're using the propsFilter filter which is a custom filter they have written for the demo: 我最初在使用ui-select演示代码时遇到了问题,因为他们使用的是propsFilter过滤器,这是他们为演示编写的自定义过滤器:

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

I am assuming you're not including this filter in your code which may be a reason you're experiencing a problem. 我假设您没有在代码中包含此过滤器,这可能是您遇到问题的原因。 You can resolve it by using angular's normal filter : 您可以使用angular的普通过滤器来解决它:

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

Alternatively, if you have multiple properties to filter you can write the propsFilter filter to filter on OR rather than AND. 或者,如果您有多个要过滤的属性,则可以编写propsFilter过滤器来过滤OR而不是AND。 If you use 'filter' to filter multiple properties it will try to match the search value across all of the properties. 如果使用“过滤器”过滤多个属性,它将尝试匹配所有属性中的搜索值。

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;
          };
    });

you can see the commit with the filter in it here: https://github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1 你可以在这里看到带有过滤器的提交: https//github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1

Although if you have some specific filtering requirements I would recommend you to write your own filter to ensure optimum performance. 虽然如果您有一些特定的过滤要求,我建议您编写自己的过滤器以确保最佳性能。

I don't know what the situation was like before Select2#4.0, but it's really not all that hard to use it without angular-ui-select (and it's one less dependency) 我不知道在Select2#4.0之前的情况是什么样的,但是如果没有angular-ui-select ,它真的不是那么难用(而且它的依赖性较小)

Just include select2 in your bower dependencies and use it in your link function within the directive: 只需在您的bower依赖项中包含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'}]...
            });
        },
    };
})

and your HTML: 和你的HTML:

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

You can also load the data from the controller via a service if you want, then just use the scope to set it! 如果需要,您还可以通过服务从控制器加载data ,然后只需使用scope进行设置!

I say this as I tried using angular-ui-select because I thought "hey it's Angular, you must use a plugin for it!", but that's not always the case :). 我说这是因为我尝试使用angular-ui-select因为我认为“嘿它是Angular,你必须使用它的插件!”,但情况并非总是如此:)。 Plus I found the docs not so helpful (call me lazy but hey) 另外我发现文档没那么有用(叫我懒,但是嘿)

I optimized the propsFilter a bit. 我对propsFilter进行了一些优化。 It is doing 它正在做

props[prop].toLowerCase();

inside the items iteration, but this actually needs to be evaluated only as many times as many properties we have. 在项目迭代中,但实际上只需要评估我们拥有的属性的次数。 Currently it was evaluated items count * props count . 目前它被评估的items count * props count

So the final optimized code looks like this: 所以最终的优化代码如下所示:

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;
    };
});    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM