Angular Bootstrap - 选择要刷新的计时问题

时间:2015-02-05 04:13:42

标签: angularjs angularjs-directive angularjs-ng-repeat bootstrap-select

我喜欢Bootstrap-Select并且我目前正在通过其他用户joaoneto/angular-bootstrap-select发出的指令帮助它并且它按预期工作,除非我尝试填充我的<select>元素一个$http或者在我的情况下是一个dataService包装器。我似乎得到了一些时间问题,数据在selectpicker显示/刷新后出现,然后我最终得到一个空的Bootstrap-Select列表..虽然使用Firebug,我确实看到了现在的值列表隐藏<select>。如果我然后进入控制台并手动执行$('.selectpicker').selectpicker('refresh')它然后工作。我通过修补并在.selectpicker('refresh')内添加$timeout暂时正常工作但是你知道它并不理想,因为我们直接在ngController中使用jQuery。 ..所以我相信这个指令可能会遗漏一个观察者或至少触发ngModel被更改或更新的东西。

Html示例代码:

<div class="col-sm-5">
    <select name="language" class="form-control show-tick" 
        ng-model="vm.profile.language" 
        selectpicker data-live-search="true"
        ng-options="language.value as language.name for language in vm.languages">
    </select>
    <!-- also tried with an ng-repeat, which has the same effect -->
</div>

然后在我的Angular Controller中:

// get list of languages from DB
dataService
    .getLanguages()
    .then(function(data) {  
        vm.languages = data;

        // need a timeout patch to properly refresh the Bootstrap-Select selectpicker 
        // not so good to use this inside an ngController but it's the only working way I have found
        $timeout(function() {
            $('.selectpicker, select[selectpicker]').selectpicker('refresh');
        }, 1);
    }); 

这是(joaoneto)在GitHub for Angular-Bootstrap-Select

上发出的指令
function selectpickerDirective($parse, $timeout) {
  return {
    restrict: 'A',
    priority: 1000,
    link: function (scope, element, attrs) {
      function refresh(newVal) {
        scope.$applyAsync(function () {
          if (attrs.ngOptions && /track by/.test(attrs.ngOptions)) element.val(newVal);
          element.selectpicker('refresh');
        });
      }

      attrs.$observe('spTheme', function (val) {
        $timeout(function () {
          element.data('selectpicker').$button.removeClass(function (i, c) {
            return (c.match(/(^|\s)?btn-\S+/g) || []).join(' ');
          });
          element.selectpicker('setStyle', val);
        });
      });

      $timeout(function () {
        element.selectpicker($parse(attrs.selectpicker)());
        element.selectpicker('refresh');
      });

      if (attrs.ngModel) {
        scope.$watch(attrs.ngModel, refresh, true);
      }

      if (attrs.ngDisabled) {
        scope.$watch(attrs.ngDisabled, refresh, true);
      }

      scope.$on('$destroy', function () {
        $timeout(function () {
          element.selectpicker('destroy');
        });
      });
    }
  };
}

2 个答案:

答案 0 :(得分:9)

angular-bootstrap-select指令的一个问题是它只监视ngModel,而不是实际填充选择中的选项的对象。例如,如果vm.profile.language默认设置为''vm.languages''选项,则选择不会更新新选项,因为{ {1}}保持不变。我在select中添加了ngModel属性,并稍微修改了angular-bootstrap-select代码。

selectModel

然后,在angular-bootstrap-select代码中,我添加了

<div class="col-sm-5">
    <select name="language" class="form-control show-tick" 
        ng-model="vm.profile.language" 
        select-model="vm.languages"
        selectpicker data-live-search="true"
        ng-options="language.value as language.name for language in vm.languages">
    </select>
</div>

现在,当if (attrs.selectModel) { scope.$watch(attrs.selectModel, refresh, true); } 更新时,选择也会更新。更好的方法可能是使用vm.languages简单地检测应该监视哪个对象,但使用此方法也允许在select中使用ngOptions

编辑:

使用ngRepeat的替代方法是自动检测要从selectModel观看的对象。

ngOptions

编辑2:

您可能最好再次调用if (attrs.ngOptions && / in /.test(attrs.ngOptions)) { scope.$watch(attrs.ngOptions.split(' in ')[1], refresh, true); } ,而不是使用refresh功能,因为您只想在element.selectpicker('refresh');时实际更新选择的值变化。我遇到了一个更新选项列表的场景,并且选择的值发生了变化,但模型没有改变,因此它与selectpicker不匹配。这解决了我的问题:

ngModel

答案 1 :(得分:0)

对不起,但是在angular-bootstrap-select代码中你添加了那段代码?我问,因为它说attrs没有定义。