我有以下指令:
.directive('radioList', function ($ionicModal) {
return {
restrict: 'A',
scope: {
selectedItem: '=selectedItem',
items: '=items'
}
};
使用以下模板html:
<div ng-repeat="item in items">
<ion-radio ng-model="selectedItem" ng-value="item">{{item.toString()}}</ion-radio>
</div>
虽然绑定在指令中,但ng-model不能在指令隔离范围或父范围上正确更新。
如果我这样做:
.directive('radioList', function ($ionicModal) {
return {
restrict: 'A',
scope: {
selectedItemInternal: '=selectedItem',
items: '=items'
},
link: function (scope, element, attr) {
Object.defineProperty(scope, 'selectedItem', {
get: function () {
return scope.selectedItemInternal;
},
set: function (value) {
scope.selectedItemInternal = value;
}
});
}
};
一切正常,我的selectItems的setter被调用。
好像是Angular中的一个错误?
更新:这是我的完整指令:
.directive('radioList', function ($ionicModal) {
return {
restrict: 'A',
scope: {
selectedItemInternal: '=selectedItem',
items: '=items',
header: '=header',
showCancel: '=showCancel',
listHide: '&listHide',
doneText: '=doneText'
},
link: function (scope, element, attr) {
element.css('cursor', 'pointer');
var modal;
scope.hide = function (result) {
modal.remove();
modal = null;
if (scope.listHide) {
scope.listHide()(result, scope.selectedItem);
}
};
// allow deselecting a radio button
var isDeselecting = false; // event fires again after scope.selectedItem changes
var hasChanged = false;
scope.click = function (event) {
if (!isDeselecting) {
hasChanged = scope.selectedItem != angular.element(event.target).scope().item;
isDeselecting = true;
} else {
if (!hasChanged) {
scope.selectedItem = null;
}
isDeselecting = false;
hasChanged = false;
}
};
// required to handle that click only fires once when double clicking
scope.doubleClick = function () {
isDeselecting = false;
hasChanged = false;
};
// necessary due to a bug in AngularJS binding ng-model in the template
Object.defineProperty(scope, 'selectedItem', {
get: function () {
return scope.selectedItemInternal;
},
set: function (value) {
scope.selectedItemInternal = value;
}
});
element.on('click', function () {
$ionicModal.fromTemplateUrl('templates/radio-list.html', {
scope: scope
}).then(function (m) {
modal = m;
// due to bug in ionic framework, scroll won't work unless we do this
ionic.keyboard.hide();
modal.show();
});
});
element.on('$destroy', function () {
if (modal) {
modal.remove();
modal = null;
}
});
}
};
})
这是我的radio-list.html
<ion-modal-view>
<div class="text-center" ng-show="header">
<h5>{{header}}</h5>
</div>
<ion-content style="position: absolute; top: {{showCancel ? '30px': '0'}}; bottom: {{showCancel ? 103 : 53}}px; border: 1px grey;border-bottom-style: solid; width: 100%;">
<div ng-repeat="item in items">
<ion-radio ng-click="click($event)" ng-dblclick="doubleClick()" ng-model="selectedItem" ng-value="item">{{item.toString()}}</ion-radio>
</div>
</ion-content>
<a class="button button-full button-energized" ng-show="showCancel"
style="position: absolute; bottom: 50px; width: 100%; margin-top: 2px; margin-bottom: 2px;"
ng-click="$event.stopPropagation();hide(false)">Cancel</a>
<a class="button button-full button-energized"
style="position: absolute; bottom: 0; width: 100%; margin-top: 2px; margin-bottom: 2px;"
ng-click="$event.stopPropagation();hide(true)">{{doneText || 'Done'}}</a>
</ion-modal-view>
以下是用法:
<label class="item item-input validated" radio-list items="locations"
selected-item="account.locationPreference">
<span class="input-label">LOCATION</span>
<input type="hidden" ng-model="account.locationPreference" name="locationPreference"
required="required">
<span ng-show="account && !account.locationPreference"
class="placeholder value">Neighborhood</span>
<span class="input-value">{{account.locationPreference}}</span>
</label>
答案 0 :(得分:1)
了解范围继承和设置值时产生的somewhat unintuitive behavior,例如ng-model
所做的事情。
在这种情况下,ng-repeat
为每次迭代创建一个子范围,所以当你有
ng-model="selectedItem"
您正在子范围上创建selectedItem
属性并在那里设置值 - 而不是在指令的隔离范围上。
作为快速解决方法,您可以直接设置$parent.selectedItem
:
<div ng-repeat="item in items">
<ion-radio ng-model="$parent.selectedItem" ng-value="item">{{item.toString()}}
</ion-radio>
</div>
<强> Demo 1 强>
或者,您可以使用bindToController
和controllerAs
语法:
return {
// ...
scope: {
// whatever you have
},
bindToController: true,
controllerAs: vm,
controller: angular.noop
}
并使用模板中的别名:
<div ng-repeat="item in vm.items">
<ion-radio ng-model="vm.selectedItem" ng-value="item">{{item.toString()}}
</ion-radio>
</div>
<强> Demo 2 强>