Angularjs 选择指令,$digest问题



我在指令中使用手表以及名为selectize的第三方插件时遇到问题。

我已经阅读了很多关于$digest/$watch的信息,但仍然遇到问题。

我下面的示例"有效",但我正在尝试防止$digest already in progress错误。

可能有更好的方法来解决这个问题,我只是不确定如何。

普伦克:http://plnkr.co/edit/3JjTsEU2BlxPWHtw6HaW?p=preview

app.directive('selectize', function($parse) {
return {
  restrict: 'A',
  require: ['ngModel'],
  scope: {
    ngModel: '=',
    options: '='
  },
  link: function(scope, el, attrs) {
    var $select = el.selectize({
      valueField: 'id',
      labelField: 'name'
    });
    var selectize = $select[0].selectize;
    // add options
    angular.forEach('options', function(tag) {
      selectize.addOption(tag);
    });
    scope.$watchCollection('options', function(newTags, oldTags) {
      // why are these the same objects?
      console.log('newTags', newTags);
      console.log('oldTags', oldTags);
      if (newTags !== oldTags) {
        // clear options
        selectize.clear();
        selectize.clearOptions();
        // add options
        angular.forEach(newTags, function(tag) {
          selectize.addOption(tag);
        });
      }
    });
    // if value changes without selecting an option,
    // set the option to the new model val
    scope.$watch('ngModel', function(val) {
      console.log('val', val);
      // selectize.setValue(val);
    });
  }
};
});
尝试将对

第三方的调用包装在如下所示的$timeout中:

$timeout(function() {
    // clear options
    selectize.clear();
    selectize.clearOptions();
    // add options
    angular.forEach(newTags, function(tag) {
      selectize.addOption(tag);
    });
}, 0);

并且不要忘记注射$timeout。

超时为零(省略值默认为 0...),我相信这可以保证在下一个摘要循环期间运行,从而防止已经在进行中的错误。 如果这是正确的,请有人插话,但我在调用某些第三方(tinyMce)javascript函数时使用了这个技巧来解决摘要错误。

请参阅Betaorbust在这篇SO帖子中的解释:AngularJS:防止调用$scope.$apply()时已经在进行的错误$digest

我最近为 Selectize 创建了一个指令,该指令支持模型和选项的双向绑定。我也不得不使用$timeout。

https://github.com/machineboy2045/angular-selectize

http://plnkr.co/edit/twGAfU?p=preview

以下是该指令的基本部分。我删除了完整版中的一些附加功能。

app.directive('selectize', function($timeout) {
  return {
    restrict: 'A',
    require: '^ngModel',
    link: function(scope, element, attrs, ngModel) {
      var config = scope.$eval(attrs.selectize);
      config.options = scope.$eval(attrs.options) || [];
      element.selectize(config);
      var selectize = element[0].selectize;
      selectize.on('option_add', refreshAngularOptions);
      scope.$watch(function(){ return ngModel.$modelValue}, refreshSelectize, true)
      function refreshAngularOptions(value, data) {
        config.options = selectize.options;
      }
      function createOption(opt){
        var newOpt = {};
        newOpt[selectize.settings.valueField] = opt;
        newOpt[selectize.settings.labelField] = opt;
        selectize.addOption(newOpt);
      }
      function refreshSelectize(value){
        $timeout(function(){
          if(angular.isArray(value))
            angular.forEach(value, createOption);
          else
            createOption(value);
          selectize.refreshOptions(false);
          selectize.setValue(value); 
        })
      }
    }
  };
});

最新更新