当使用 ng-init 初始化模型时,默认 select 在 ngoptions 中不起作用

Default select not working in ngoptions when model initialized with ng-init

我有一个级联 select,第二个下拉菜单基于第一个下拉菜单出现 selection。出现一个额外的空白选项,这不是下拉列表预期行为的一部分。

<select ng-init="order.attempt_status_sub = order.attempt_status_sub || subStatuses[0].name" 
    data-ng-model="order.attempt_status_sub" ng-options="subStatus.name as 
    subStatus.name for subStatus in subStatuses"> 
</select>

如何避免空的额外 select 出现在下拉列表中?

我的级联下拉菜单的代码是

    <div class="form-group" ng-class="{ 'has-error' : submitted && orderForm.content.$invalid}">
      <div class="controls">
        <select ng-change="getSubStatuses(order.attempt_status)" data-ng-model="order.attempt_status" ng-options="status.name as status.name for status in statuses">
        </select>
      </div>
    </div>

    <div class="form-group" ng-show="subStatuses.length" ng-class="{ 'has-error' : submitted && orderForm.content.$invalid}">
      <div class="controls">
        <select ng-init="order.attempt_status_sub = order.attempt_status_sub || subStatuses[0].name" data-ng-model="order.attempt_status_sub" ng-options="subStatus.name as subStatus.name for subStatus in subStatuses">
        </select>
      </div>
    </div>
$scope.getSubStatuses = function(attempt_status) {

    var statuses = $scope.statuses;
    for(var index in statuses) {
        if(statuses[index].name === attempt_status) {

            if(statuses[index].children) {
                $scope.subStatuses = statuses[index].children;
            } else {
                $scope.subStatuses = [];
            }
            break;
        }
    }
};

我假设您正在为异步绑定数据设置此项。 ng-init 对于这个目的来说真的很糟糕。拇指规则是不要将 ng-init 用于控制器应该做的事情。您应该在控制器中设置视图模型。异步绑定数据时它可能失败的原因是因为未监视 ng-init 的表达式。因此在第一次渲染期间它只 运行s 一次并且 subStatuses 尚未填充并且它回退到显示默认的空选项。即使在稍后的摘要循环中填充数据并更新视图,ng-init 表达式也不会再次 运行。

From Doc

The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.

所以只需在控制器中初始化它,而不是使用 ng-init。

$scope.getSubStatuses = function(attempt_status) {

    var statuses = $scope.statuses;
    for(var index in statuses) {
        if(statuses[index].name === attempt_status) {

            if(statuses[index].children) {
                $scope.subStatuses = statuses[index].children;
            } else {
                $scope.subStatuses = [];
            }
            break;
        }
    }
    //Initialize the model here, assuming $scope.order is already initialized
    $scope.order.attempt_status_sub = ($scope.subStatuses[0] ||{}).name;
};

angular.module('app', []).controller('ctrl', function($scope, $timeout) {

  $timeout(function() {
    $scope.subStatuses = [{
      name: 'test1'
    }, {
      name: 'test2'
    }, {
      name: 'test3'
    }];

    $scope.order = {
      attempt_status_sub1: $scope.subStatuses[0].name
    };

  });



});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  With Ng-Init
  <select ng-init="order.attempt_status_sub = order.attempt_status_sub || subStatuses[0].name" data-ng-model="order.attempt_status_sub" ng-options="subStatus.name as 
    subStatus.name for subStatus in subStatuses">
  </select>

  With controller initialization.

  <select data-ng-model="order.attempt_status_sub1" ng-options="subStatus.name as 
    subStatus.name for subStatus in subStatuses">
  </select>
</div>