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 工作不正常
如何在angularjs中的选择框或内部选项中使用ng-model?