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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26506713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:58:46  来源:igfitidea点击:

AngularJs: How make ui-select working properly?

javascripthtmlangularjsui-select

提问by FrancescoMussi

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. It is almost working, except from the fact that i have problems to get and display the pre-existent tags.

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

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:

尝试 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. 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. In both cases, working and not, i get several error message of the same kind:

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

Cannot read property 'length' of undefined.

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

ATTEMPT 2:

尝试 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):

问题):

How can i make ui-select properly working? (currently v0.8.3) There is a problem of conflict?

我怎样才能让 ui-select 正常工作?(目前v0.8.3)有冲突的问题吗?

How can i properly call pre-existent data from the server?

如何从服务器正确调用预先存在的数据?

Thank you very much!

非常感谢!

回答by Nick Martin

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 propsFilterfilter 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. If you use 'filter' to filter multiple properties it will try to match the search value across all of the properties.

或者,如果您有多个要过滤的属性,您可以编写 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;
          };
    });

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.

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

回答by a7omiton

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 select2in your bower dependencies and use it in your linkfunction within the directive:

只需包含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 datafrom the controller via a service if you want, then just use the scopeto set it!

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

I say this as I tried using angular-ui-selectbecause I thought "hey it's Angular, you must use a plugin for it!", but that's not always the case :). Plus I found the docs not so helpful (call me lazy but hey)

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

回答by michal.jakubeczy

I optimized the propsFilter a bit. It is doing

我稍微优化了 propsFilter。它正在做

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 迭代中,但这实际上只需要评估我们拥有的属性的次数。目前它被评估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;
    };
});