【问题标题】:Angularjs: select not updating when ng-model is updatedAngularjs:在更新ng-model时选择不更新
【发布时间】: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>

【问题讨论】:

    标签: javascript angularjs angular-ngmodel


    【解决方案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。至少你有另一种方式来做这件事,并且理解为什么你的原始代码没有按预期工作。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-10-17
          • 2016-03-08
          • 1970-01-01
          • 2014-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多