我有一个动态显示复选框列表的指令。它有一个名为options
的参数,它应该是如下所示的数组,以便正确显示复选框列表。例如:
var options = [
{
id: 1,
label: 'option #1'
},
{
id: 2,
label: 'option #2'
},
{
id: 3,
label: 'option #3'
}
];
因此,通过将此数组传递给我的指令,将显示一组三个复选框。
此外,该指令需要ngModel
,其结果是选中/取消选中复选框(此对象始终被初始化)。例如:
var result = {
"1": true,
"2": true,
"3": false
};
这种情况意味着会检查第一个和第二个复选框(包含id=1
和id=2
的选项),第三个选项(id=3
选项)未选中。
template.html
<div ng-repeat="option in options track by $index">
<div class="checkbox">
<label>
<input type="checkbox"
ng-model="result[option.id]">
{{ ::option.label }}
</label>
</div>
</div>
directive.js
angular
.module('myApp')
.directive('myDirective', myDirective);
function myDirective() {
var directive = {
templateUrl: 'template.html',
restrict: 'E',
require: 'ngModel',
scope: {
options: '='
},
link: linkFunc
};
return directive;
function linkFunc(scope, element, attrs, ngModel) {
scope.result;
ngModel.$render = setResult;
function setResult() {
scope.result = ngModel.$viewValue;
};
};
};
无论我在哪里使用我的指令,我希望能够在ngModel
更改时触发函数。当然,我想使用ngChange
来实现这一目标。到目前为止,我有以下内容:
<my-directive
name="myName"
options="ctrlVM.options"
ng-model="ctrlVM.result"
ng-change="ctrlVM.selectionChanged()">
</my-directive>
但只要模型发生变化,就不会触发.selectionChanged()
函数。任何人都知道为什么这不起作用,因为我希望它能起作用?
答案 0 :(得分:0)
首先,请尝试提供jsfiddle,codepen等代码段链接,以便其他人轻松回答您的问题。
您遇到的问题是,在传递对象引用时,您永远不会更新ctrlVM.result
对象,即使您通过调用ngModel.$setViewValue()
手动更新模型,该引用也不会更改。
要解决此问题,只需通过手动调用ngModel.$setViewValue()
来更新模型并传入新的Object,以便引用更改并触发ngChange
指令逻辑。
我已经添加了这样做的逻辑,它将成功触发更改。请看下面的代码:
angular
.module('myApp', [])
.directive('myDirective', myDirective)
.controller('MyController', function($timeout) {
var vm = this;
vm.options = [{
id: 1,
label: 'option #1'
}, {
id: 2,
label: 'option #2'
}, {
id: 3,
label: 'option #3'
}];
vm.result = {
"1": true,
"2": true,
"3": false
};
vm.selectionChanged = function() {
vm.isChanged = true;
$timeout(function() {
vm.isChanged = false;
}, 500)
}
});
function myDirective() {
var directive = {
templateUrl: 'template.html',
restrict: 'E',
require: 'ngModel',
scope: {
options: '='
},
link: linkFunc
};
return directive;
function linkFunc(scope, element, attrs, ngModel) {
scope.result;
ngModel.$render = setResult;
function setResult() {
scope.result = ngModel.$viewValue;
};
scope.updateValue = function(val) {
ngModel.$setViewValue(Object.assign({}, val))
}
};
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div ng-app="myApp">
<script type="text/ng-template" id="template.html">
<div ng-repeat="option in options track by $index">
<div class="checkbox">
<label>
<input type="checkbox"
ng-model="result[option.id]" ng-click="updateValue(result)">
{{ ::option.label }}
</label>
</div>
</div>
</script>
<div ng-controller="MyController as ctrlVM">
<my-directive name="myName" options="ctrlVM.options" ng-model="ctrlVM.result" ng-change="ctrlVM.selectionChanged()">
</my-directive>
<div> Data: {{ctrlVM.result}} </div>
<div> isChanged: {{ctrlVM.isChanged}} </div>
</div>
</div>
答案 1 :(得分:0)
@Gaurav
正确识别了问题(永远不会调用ng-change
,因为对象引用不会更改)。这是一个更简单的解决方案,无需手动克隆到控制器的模型中:
为ng-change
属性添加绑定:
scope: {
options: '=',
ngChange: '&' // Add this, creates binding to `ctrlVM.selectionChanged()`
}
在您的复选框模板中添加ng-change
:
<input type="checkbox"
ng-model="result[option.id]" ng-change="ngChange()">
现在,当任何复选框更改时,它将自动调用外部ng-change
函数,而无需克隆到模型中的中间步骤。