【问题标题】:AngularJs: How make ui-select working properly?AngularJs:如何使 ui-select 正常工作?
【发布时间】:2014-12-17 20:37:24
【问题描述】:

情况:

我正在制作一个必须使用 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) 有冲突的问题吗?

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

非常感谢!

【问题讨论】:

    标签: javascript html angularjs ui-select


    【解决方案1】:

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

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

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

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

    <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

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

    【讨论】:

    • 感谢您指出propsFilter 是一种自定义方法。这可能为我节省了几个小时的抓挠时间。我要提交一个 PR 到 ui-select 来说明。
    • 您好,感谢您的解释。我开始使用您提供的代码,但遇到了错误。事实证明,这里发布的内容与您引用的提交有所不同:内部 for 应该是:for (var i = 0; i &lt; keys.length; i++) 以避免陷入无限循环。
    • 哦hhhhhhhhh那个自定义propsFilter!谢谢!这是数小时、数小时和数小时令人头疼的结束!
    【解决方案2】:

    不知道Select2#4.0之前的情况是怎样的,但是没有angular-ui-select真的没那么难用(而且少了一个依赖)

    只需在您的 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'}]...
                });
            },
        };
    })
    

    和你的 HTML:

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

    您也可以根据需要通过服务从控制器加载data,然后只需使用scope 进行设置!

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

    【讨论】:

      【解决方案3】:

      我稍微优化了 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;
          };
      });    
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-03
        • 1970-01-01
        • 1970-01-01
        • 2018-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多