我正在尝试使用<input type="checkbox">
构建一个自定义复选框指令(以便能够根据我的喜好设置它)。它应该像人们期望的那样工作;更新模型应更新视图,单击该框应更新模型,它应该监听required
指令(验证应该有效)。
我目前有以下指令,完全符合预期:
'use strict';
angular.module('directives.checkbox', [])
.directive('checkbox', [function () {
return {
restrict: 'A',
require: 'ngModel',
replace: true,
template: '<span class="checkbox"></span>',
link: function (scope, elem, attrs, ctrl) {
elem.bind('click', function () {
scope.$apply(function () {
elem.toggleClass('checked');
ctrl.$setViewValue(elem.hasClass('checked'));
});
});
ctrl.$render = function () {
if (!elem.hasClass('checked') && ctrl.$viewValue) {
elem.addClass('checked');
} else if (elem.hasClass('checked') && !ctrl.$viewValue) {
elem.removeClass('checked');
}
};
}
}
}]);
它只是<span>
的CSS类checkbox
和另一个CSS类checked
的已检查状态。但是,使用jQuery切换类并像我一样更新视图似乎没有像角度一样(或最佳实践)。我宁愿使用ng-class
和ng-click
指令,但这意味着我需要使用一个隔离的范围(以避免在同一页面上使用多个复选框时范围状态冲突)。出于某种原因,隔离范围会使角度停止在$render()
上调用ctrl
。
有没有人知道这是否是正确的方法,或者是否有更像角度的方法仍能解决我的要求?
答案 0 :(得分:1)
首先,我相信如果样式是你的问题,你肯定可以通过css自定义输入,而不是创建一个必须模仿输入复选框的指令。
话虽这么说,添加和删除类的角度方式实际上是在模板中包含作为表达式或作为ngClass的参数。 您还可以通过在模板中包含ngClick来避免绑定。
app.directive('myCheckbox', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<span class="checkbox" ng-class="{checked: isChecked}" ng-click="toggleMe()"></span>',
scope: { isChecked: '=?'},
link: function(scope, elem, attrs) {
scope.isChecked = true;
scope.toggleMe = function() {
scope.isChecked = !(scope.isChecked);
}
}
});
Here is a little plunk解释我的意思
答案 1 :(得分:0)
$ render函数。我们可以监视模型更改并检查元素状态并相应地更新UI,而不是提供渲染功能。
以下是指令代码。
var app = angular.module('RadioOrCheck', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive('radioOrCheck', radioOrCheckDirective);
function radioOrCheckDirective() {
return {
require: 'ngModel',
restrict: 'A',
scope: false,
link: link
};
function link(scope, element, attrs) {
element.addClass('hidden-input').wrap('<label/>');
element.parent().addClass(attrs.type).append('<span/>');
scope.$watch(attrs.ngModel, function updateUI() {
element.parent().toggleClass('checked', jQuery(element).is(':checked'));
});
attrs.$observe('label', function(newLabel) {
element.parent().find('span').text(newLabel);
});
}
}
.hidden-input {
border: 0;
clip: rect(0 0 0 0);
height: 0;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 0;
}
.radio {
display: block;
cursor: pointer;
color: red;
}
.radio.checked {
color: green;
}
.checkbox {
display: block;
cursor: pointer;
color: red;
}
.checkbox.checked {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="1" />
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="2" />
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="3" />
<br/>
Here is the working plunker。这里的输入字段是模拟默认值,CSS可以根据您的需要进行调整。
答案 2 :(得分:0)
$ render函数。我们可以监视模型更改并检查元素状态并相应地更新UI,而不是提供渲染功能。
以下是指令代码。
var app = angular.module('RadioOrCheck', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive('radioOrCheck', radioOrCheckDirective);
function radioOrCheckDirective() {
return {
require: 'ngModel',
restrict: 'A',
scope: false,
link: link
};
function link(scope, element, attrs) {
element.addClass('hidden-input').wrap('<label/>');
element.parent().addClass(attrs.type).append('<span/>');
scope.$watch(attrs.ngModel, function updateUI() {
element.parent().toggleClass('checked', jQuery(element).is(':checked'));
});
attrs.$observe('label', function(newLabel) {
element.parent().find('span').text(newLabel);
});
}
}
&#13;
.hidden-input {
border: 0;
clip: rect(0 0 0 0);
height: 0;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 0;
}
.radio {
display: block;
cursor: pointer;
color: red;
}
.radio.checked {
color: green;
}
.checkbox {
display: block;
cursor: pointer;
color: red;
}
.checkbox.checked {
color: green;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="RadioOrCheck">
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<input radio-or-check="" type="checkbox" ng-model="cbModel" data-label="CB Label" />
<br/>
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="1" />
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="2" />
<br/>
<input radio-or-check="" type="radio" ng-model="rModel" data-label="R Label" value="3" />
<br/>
</div>
&#13;
Here is the working plunker。这里的输入字段是模拟默认值,CSS可以根据您的需要进行调整。