Angularjs:在更新ng-model时选择不更新

Posted

技术标签:

【中文标题】Angularjs:在更新ng-model时选择不更新【英文标题】:Angularjs: select not updating when ng-model is updated 【发布时间】:2014-11-30 10:30:30 【问题描述】:

我创建了以下示例,以便您可以准确了解发生了什么:http://jsfiddle.net/8t2Ln/101/

如果我使用 ng-options,也会发生同样的事情。我这样做有不同的原因,但为了简化示例,省略了该部分。

如您所见,默认情况下它有两个选项。我在选择旁边显示了 ng-model 的选定值,以便您可以看到它是什么。当您使用顶部添加第三个选项时,它将值设置为该新选项的值,正如选择旁边显示的 ng-model 值所证明的那样,但选择本身不会更改以显示正确的值已选中。

以下是链接中的示例代码:

var testApp = angular.module('testApp', ['ngRoute']);

testApp.controller('Ctrl', function ($scope) 

    $scope.newInput = '';
    $scope.inputDevice = [
        
            value: '1',
            label: 'input1'
        ,
        
            value: '2',
            label: 'input2'
        
    ];
    $scope.selectedDevice = '';

    $scope.addType = function () 
        var newElem = 
            label: $scope.newInput,
            value: '3'
        ;
        $scope.inputDevice.push(newElem);
        $scope.selectedDevice = newElem.value;
    ;


);

这里是html

<div ng-app="testApp">
    <div ng-controller="Ctrl">
        <p>
            <input type="text" ng-model="newInput" />
            <br />
            <button ng-click="addType()">Add Type</button>
        </p>
        <select ng-model="selectedDevice">
            <option></option>
            <option ng-repeat="i in inputDevice" value=" i.value "> i.label  -  i.value </option>
        </select>
         selectedDevice </div>
</div>

【问题讨论】:

【参考方案1】:

这正是您不应该使用ngRepeat 来呈现选择选项的原因。你应该改用ngOptions

<select ng-model="selectedDevice" 
        ng-options="i.value as (i.label + '-' + i.value) for i in inputDevice">
    <option></option>
</select>

一般来说,避免使用 ngRepeat 来呈现选择选项。至少有两个很好的理由。 ngRepeat 每次迭代都会创建单独的子作用域,这在选项标记的情况下是不需要的。另一个重要的警告是,使用ngRepeat,您只能将 select 绑定到字符串等原语,但您无法使用它将对象写入 ngModel。

下面是一个演示。

angular.module('demo', []).controller('DemoController', function($scope) 

    $scope.newInput = '';
    $scope.inputDevice = [
    	value: '1', label: 'input1', 
        value: '2', label: 'input2'
    ];
    
    $scope.selectedDevice = '';
    $scope.addType = function() 
        var newElem = 
            label: $scope.newInput,
            value: Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1
        ;
        $scope.inputDevice.push(newElem);
        $scope.selectedDevice = newElem.value;
        $scope.newInput = '';
    ;

);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
    <form ng-submit="addType()">
        <input type="text" ng-model="newInput" />
        <button type="submit">Add Type</button>
    </form>
    <select ng-model="selectedDevice" ng-options="i.value as (i.label + ' - ' + i.value) for i in inputDevice">
        <option>Select</option>
    </select>
     selectedDevice 
</div>

【讨论】:

很公平。我以为我两种方法都试过了,但显然没有。 @dfsq 完美答案。点赞!我只是以为 Jhorra 不想使用ng-options 如果我使用ng-options,我会得到一个空项目。出于这个原因,我在某些情况下不使用 ng-otpions。 @BMS Empty item表示你没有正确设置ngModel,所以Angular不知道选择什么选项。 为了澄清,没有空白的第一项,在你的控制器中设置 ng-model 变量的值,或者只有在设置后才让 ng-if 在 dom 上渲染它,如果值是异步获得的。【参考方案2】:

我遇到了同样的问题。为我解决的问题是将数字转换为字符串。示例:

$scope.selectedDevice = "" + newElem.value; 

【讨论】:

【参考方案3】:

更新 ng-model 时,我遇到了相同的 select 不更新问题。我正在从基于键值对从数组中提取对象的函数中检索 ng-model 的值。

在执行此操作时,返回的对象具有 hashkey 属性 $$hashKey: "object:115"

当我使用 angular.copy 创建对象的副本时出现问题,该副本剥离了这个“哈希键”属性,因此不会被选中。

我重新整理代码后,在angular.copy之后获取ng-model的值,问题解决了

ConstructorReviewers: function (oItem) 
      this.PERSON_ID = oItem.PERSON_ID;
      this.CHAIR_PERSON = oItem.CHAIR_PERSON;

      /* // Commented this part and added it to EditItem function      
      this.oDepartment = CommonFactory.FindItemInArray(vm.oCommittee.arrDepartments, 'NAME', this.DEPARTMENT, 'item');
      */    
      this.EditItem = function () 
           vm.EditItemOriginal = this;
           angular.copy(this, vm.EditItem); // After this update the ng-model into vm.EditItem.oTitle object
           vm.EditItem.oTitle = CommonFactory.FindItemInArray(vm.oCommittee.arrTitles, 'TITLE', vm.EditItem.TITLE, 'item');
           vm.Popup.ShowPopup(true, 'new_edit', Constants.Mentoring.Popup.Edit);
      

【讨论】:

【参考方案4】:

我遇到了类似的问题,原因是我的键是一个数字,但是当我尝试设置另一个值时,我发送了一个字符串。这种情况下的解决方法是强制将模型值设置为与键相同的类型。

例如:

<select ng-model="model" ng-options="option. key  as option. label  for option in options">
    <option value=""> emptyLabel </option>
</select>
if (scope.options.length > 0) 
    scope.keyType = typeof(scope.options[0][scope.key]);

...

if (scope.keyType == 'number') 
    scope.model = parseInt(newVal, 10);
 else 
    scope.model = newVal;
 

【讨论】:

【参考方案5】:

问题在于,由于您没有使用ng-options,因此在您设置新的selectedDevice 时浏览器还没有完成渲染。如果您开始使用ng-options,则可以使用此解决方法。使用$timeout 包装您的$scope.selectedDevice = newElem.value; 以确保它在浏览器完成使用ng-repeat 呈现更改后运行。

我还添加了代码以在连续添加时递增下一个值,因为将其硬编码为“3”意味着即使添加更多选项也会继续选择第三个选项。

var testApp = angular.module('testApp', ['ngRoute']);

testApp.controller('Ctrl', function($scope, $timeout) 

  $scope.newInput = '';
  $scope.inputDevice = [
    value: '1',
    label: 'input1'
  , 
    value: '2',
    label: 'input2'
  ];
  $scope.selectedDevice = '';

  $scope.addType = function() 
    var last = Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1;
    var newElem = 
      label: $scope.newInput,
      value: last.toString()
    ;
    $scope.inputDevice.push(newElem);
    $timeout(function() 
      $scope.selectedDevice = newElem.value;
    , 0);
  ;

);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular-route.js"></script>

<div ng-app="testApp">
  <div ng-controller="Ctrl">
    <p>
      <input type="text" ng-model="newInput" />
      <br />
      <button ng-click="addType()">Add Type</button>
    </p>
    <select ng-model="selectedDevice">
      <option></option>
      <option ng-repeat="i in inputDevice" value=" i.value " ng-selelected=" selectedDevice == i.value "> i.label  -  i.value </option>
    </select>
     selectedDevice 
  </div>
</div>

【讨论】:

我使用ng-repeat 制定了一个解决方案,因为我想我误解了你想使用它而不是ng-options。至少你有另一种方式来做这件事,并且理解为什么你的原始代码没有按预期工作。

以上是关于Angularjs:在更新ng-model时选择不更新的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS - 选择的 ng-model 工作不正常

没有 ng-model AngularJS 选择不起作用

如何在angularjs中的选择框或内部选项中使用ng-model?

如何让 ng-model 不立即更新?

如何根据 angularjs 中的选定对象更新 ng-model?

Angularjs模型数组不使用模板更新