ng-change检测选择框中ng-model是否为null或无效,并选择第一个有效选项

时间:2016-01-21 22:55:21

标签: javascript angularjs

我有数百个这样的案例(所以修复必须是全局的,而不仅仅是这个特定的例子)

有很多像这样的选择框:

<select ng-model="selectedItem">
 <option ng-repeat="item in items | filter:attributes" value="{{item.id}}">{{item.name}}</option>
</select>

selectedItem变量为null(它将始终初始化为null,在此特定情况下无法在控制器中更改)。

我想弄清楚的是全局观看视图中所有<select>元素的方法,看看该ng-model框的<select>变量是null如果null将其设置为该选择框中的第一个有效选项,则只要范围发生变化,就需要检查ng-model是否为null并自动选择第一个有效选项

1 个答案:

答案 0 :(得分:2)

要实现的关键是你可以定义多个具有相同名称的Angular指令,并且所有这些指令都将针对匹配元素运行。

这非常强大,因为它使您能够扩展内置指令或第三方指令等功能。

使用这个,我能够创建一个select指令,只要模型值为null,它就会在列表中选择第一个有效选项。

但是,如果从列表中删除所选项目(它会变回空白),它不会做的一件事就是应对。但希望这足以让你开始。

var app = angular.module('stackoverflow', []);

app.controller('MainCtrl', function($scope) {
  $scope.selectedItem = null;
  $scope.items = [1, 2, 3, 4].map(function(id) {
    return {
      id: id,
      visible: true,
      text: 'Item ' + id
    };
  });
});

app.directive('select', function() {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function($scope, $elem, $attrs, ngModel) {
      // don't do anything for selects without ng-model attribute
      if (!ngModel) return;
      // also allow specifying a special "no-default" attribute to opt out of this behaviour
      if ($attrs.hasOwnProperty('noDefault')) return;
      // watch the model value for null
      var deregWatch = $scope.$watch(function() {
        return ngModel.$modelValue;
      }, function(modelValue) {
        if (modelValue === null) {
          // delay to allow the expressions to be interpolated correctly
          setTimeout(function() {
            // find the first option with valid text
            var $options = $elem.find('option'),
              $firstValidOption, optionText;
            for (var i = 0, len = $options.length; i < len; i++) {
              optionText = $options.eq(i).text();
              if (optionText !== '' && !optionText.match(/^(\?|{)/)) {
                $firstValidOption = $options.eq(i);
                break;
              }
            }
            if ($firstValidOption) {
              $firstValidOption.prop('selected', true);
              ngModel.$setViewValue($firstValidOption.attr('value'));
              // trigger a digest so Angular sees the change
              $scope.$evalAsync();
            }
          }, 0);
        }
      });

      // clean up in destroy method to prevent any memory leaks
      var deregDestroy = $scope.$on('$destroy', function() {
        deregWatch();
        deregDestroy();
      });
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="stackoverflow">
  <div ng-controller="MainCtrl">
    <select ng-model="selectedItem">
      <option ng-repeat="item in items | filter:{visible:true} track by item.id" value="{{item.id}}">{{item.text}}</option>
    </select>
    <p>Visible items:</p>
    <ul>
      <li ng-repeat="item in items track by item.id">
        <label>
          <input type="checkbox" ng-model="item.visible">{{item.text}}
        </label>
      </li>
    </ul>
  </div>
</div>