AngularJS下拉指令通过双向绑定设置所选项目

时间:2015-05-14 19:08:26

标签: angularjs drop-down-menu angularjs-directive

我有一个angularjs下拉指令。我希望能够传递我想要选择的项目的id作为指令的属性。像这样:

<dropdown selected-item-id="ctrl.selectedItemId"></dropdown>  

我实现了这个并且没有用。如果我在指令代码上显示itemId的值,我可以看到正确的值,但下拉选择不会更新。这是相关的代码:

(function () {
	'use strict';
	var dropdown = function ($state, service) {
		return {
			restrict: 'E',
			replace: true,
			templateUrl: '/dropdown.html',
			scope: {
			    selectedItemId:"="
			},
			link: function (scope, elem, attr) {
              service
                .getItems()
                .then(function (items) {
                    scope.items = items;
                 });
			}
		};
	};
	dropdown.$inject = ['$state', 'service'];
	angular.module('app').directive('dropdown', dropdown);
})();
<select class="form-control"
        ng-model="selectedItemId"
        ng-options="item.id as item.name for item in items">
    <option value="" selected disabled>Select an item</option>
</select>

就像我说的,如果我在指令模板上显示selectedItemId(例如作为其中一个选项),我会看到正确的id值,但是下拉选择不会改变。

有什么想法吗?

修改 我在下拉列表的属性上输入了一个拼写错误(在输入代码时发生了,我的编辑器上的实际代码是正确的),item-id为selected-item-id

3 个答案:

答案 0 :(得分:2)

根据您的html代码,您没有将所选值绑定到item-id。您将所选值绑定到selected-item-id。

尝试将html更改为:

 <dropdown selected-item-id="ctrl.selectedItemId"></dropdown>

答案 1 :(得分:1)

看起来您可能在$ digest周期中遇到竞争条件。如果您从代码的第一个版本的服务回调中调用$ apply(),它应该可以工作。但是,你会产生副作用,角度会不时地抱怨$ apply正在进行中,所以你的代码的第二个版本应该可以解决问题。

答案 2 :(得分:0)

我不确定为什么它不能像我一样工作,但我做了一些改变,现在它工作正常。这是我做的(解释是作为对源代码的评论而包含在内)

&#13;
&#13;
//Here I use the selectedItem bidirectional binding on the .then of my service call
//to get the id of the items that's supposed to be selected.
//Then, I filter the array of items using that id, so I get the actual object that matches the id.
//Finally, I set the scope object "selectedItem" to that object I just got. 
//The "selectedItem" object is what's bound to the select via ng-model so that does the selection.
(function () {
	'use strict';
	var dropdown = function ($state, service) {
		return {
			restrict: 'E',
			replace: true,
			templateUrl: '/dropdown.html',
			scope: {
			    selectedItemId:"="
			},
			link: function (scope, elem, attr) {
              service
                .getItems()
                .then(function (items) {
                    scope.items = items;
                var selectedItem = $filter('filter')(items, { id:     scope.selectedItemId })[0];
				        scope.selectedItem = selectedItem;
                 });
			}
		};
	};
	dropdown.$inject = ['$state', 'service'];
	angular.module('app').directive('dropdown', dropdown);
})();
&#13;
<!--Here I replaced the ng-model to use an object rather than an id and did the same on the ng-options -->
<select class="form-control"
        ng-model="selectedItem"
        ng-options="item as item.name for item in items">
    <option value="" selected disabled>Select an item</option>
</select>
&#13;
&#13;
&#13;