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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26211573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:32:11  来源:igfitidea点击:

Angularjs: select not updating when ng-model is updated

javascriptangularjsangular-ngmodel

提问by Jhorra

I've created the following example so you can see exactly what is happening: http://jsfiddle.net/8t2Ln/101/

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

The same thing happens if I use ng-options. I have a different reason for doing it this way, but for the simplification of the example left that part out.

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

As you can see it has by default two options. I'm displaying the selected value of the ng-model next to the select so you can see what it is. When you use the top piece to add a third option it sets the value to the value of that new option as is evidenced by the displayed ng-model value next to the select, but the select itself doesn't change to show the correct value selected.

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

Below is the sample code at the link:

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

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;
    };


});

And here is the html:

这是 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>

回答by dfsq

This is exactly why you should not use ngRepeatto render select options. You should use ngOptionsinstead:

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

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

In general, avoid using ngRepeat for rendering select options. There are at least two good reasons. ngRepeatcreates separate child scope per iteration, which is not needed in case of option tag. Another important caveat is that with ngRepeatyou can only bind select to primitives like strings, but you won't be able to write object to ngModel with it.

通常,避免使用 ngRepeat 来渲染选择选项。至少有两个很好的理由。ngRepeat每次迭代创建单独的子范围,在选项标签的情况下不需要。另一个重要的警告是,ngRepeat您只能将 select 绑定到像字符串这样的原语,但您将无法使用它向 ngModel 写入对象。

Here is a demo below.

下面是一个演示。

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>

回答by JME

The problem is that, since you're not using ng-optionsthe browser had not finished rendering at the point when you set the new selectedDevice. If you're set on on using ng-optionsyou can use this workaround. Use $timeoutto wrap your $scope.selectedDevice = newElem.value;to ensure it runs after the browser has finished rendering the changes with ng-repeat.

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

I also added code to increment the next value on successive adds because hardcoding it to '3' meant that the third option would continually be selected even when more are added.

我还添加了代码以在连续添加时增加下一个值,因为将其硬编码为“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>

回答by Romain

I had a similar problem and the reason was that my key was a number, but when trying to set another value I was sending a string. The workaround in this case is to force to set the model value to the same type as the key.

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

eg:

例如:

<select ng-model="model" ng-options="option.{{ key }} as option.{{ label }} for option in options">
    <option value="">{{ emptyLabel }}</option>
</select>
<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;
} 

回答by Mahesh

I had the same issue of select not updating when ng-model is updated. I was retrieving the value for ng-model from a function which extracted the object from the array based on a key,value pair.

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

In doing this, the returned object had the hashkey property $$hashKey: "object:115"

在这样做时,返回的对象具有 hashkey 属性 $$hashKey: "object:115"

The problem occurred when I created a copy of the object using angular.copy which stripped off this 'hashkey' property and hence would not get selected.

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

After I reorganized the code, to get ng-model value after angular.copy, the issue was resolved

重新整理代码后,在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);
      }
}

回答by Malek Hijazi

I had the same problem. What solved it for me is converting the number to a string. Example:

我有同样的问题。为我解决的是将数字转换为字符串。例子:

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