Какой лучший способ реализовать один флажок с тремя состояниями в angularjs?
Существует ли простой способ разместить один флажок с тремя состояниями на веб-странице и связать его с булевой моделью, чтобы последняя могла принять true
, false
или же null
ценности?
Самое близкое решение, которое я нашел до сих пор, это http://jsfiddle.net/HB7LU/454/ но у него есть недостаток при настройке начального состояния просмотра (так как нет способа получить значение модели во время первого рендеринга). Любые другие предложения касаются нескольких дочерних флажков и решают проблему, наблюдая за ними.
5 ответов
http://jsfiddle.net/xJhEG/ Я сделал это в коммерческом проекте. Тристаты - это правда, ложь, ноль (не "неизвестно")
.directive('indeterminate', [function() {
return {
require: '?ngModel',
link: function(scope, el, attrs, ctrl) {
var truthy = true;
var falsy = false;
var nully = null;
ctrl.$formatters = [];
ctrl.$parsers = [];
ctrl.$render = function() {
var d = ctrl.$viewValue;
el.data('checked', d);
switch(d){
case truthy:
el.prop('indeterminate', false);
el.prop('checked', true);
break;
case falsy:
el.prop('indeterminate', false);
el.prop('checked', false);
break;
default:
el.prop('indeterminate', true);
}
};
el.bind('click', function() {
var d;
switch(el.data('checked')){
case falsy:
d = truthy;
break;
case truthy:
d = nully;
break;
default:
d = falsy;
}
ctrl.$setViewValue(d);
scope.$apply(ctrl.$render);
});
}
};
}])
Вот моя скрипка, начиная с TruongSinh и меняя
без
var truthy = true;
var falsy = false;
var nully = null;
Вы должны воспользоваться неопределенным состоянием <input type="checkbox">
,
Веб-документы MDN: существует неопределенное состояние флажков, в которых оно не отмечено или не проверено, но не определено. Это устанавливается с помощью неопределенного свойства объекта HTMLInputElement через JavaScript (его нельзя установить с помощью атрибута HTML).
ПЛАНКЕР: ТРИСТАТ ДИРЕКТИВ
HTML
<label>
<input type="checkbox" ng-model="state" indeterminate /> {{state}}
</label>
ДИРЕКТИВА
app.directive('indeterminate', function() {
return {
restrict: 'A',
scope: {
model: '=ngModel'
},
link: function(scope, el, attrs, ctrl) {
var states = [true, false, undefined];
var index = states.indexOf(scope.model);
setIndeterminate();
el.bind('click', function() {
scope.model = states[++index % 3];
setIndeterminate();
});
function setIndeterminate() {
scope.$applyAsync(function() {
el[0].indeterminate = (scope.model === undefined);
});
}
}
};
});
ДОПОЛНИТЕЛЬНО: Если вы хотите добавить строку для представления неопределенного состояния, используйте этот CSS
input:indeterminate:after {
content: "indeterminate";
padding-left: 20px;
display: inline-block;
width: 80px;
}
Я создал директиву, которую вы можете использовать. Флажок с тремя состояниями AngularJS Директива на GitHub
Также есть пост о том, как он был построен: " Создание Директивы Ангулра" Флажок с тремя состояниями
Вы можете попробовать ДЕМО
И директива выглядит так:
angular.module("threeStateCheckbox", [])
.directive("threeStateCheckbox", ['$compile', function($compile){
return {
restrict: "A",
transclude: true,
require: 'ngModel',
link: function(scope, element, attrs, ngModel){
var states = [true, false, null];
var classNames = ["checked", "unchecked", "clear"];
scope.click = function(){
var st;
states.map(function(val, i){
if(ngModel.$modelValue === val){
st = states[(i+1)%3];
}
});
ngModel.$setViewValue(st);
ngModel.$render();
};
scope.tscClassName = function(){
var className;
states.map(function(val, i){
if(ngModel.$modelValue=== val){
className = classNames[i];
}
});
return className;
};
element.attr("class", "tri-sta-che ");
element.attr("ng-click", "click()");
element.attr("ng-class", "tscClassName()");
element.removeAttr("three-state-checkbox");
$compile(element)(scope);
}
};
}]);
Поскольку все предыдущие ответы не работают, начиная с AngularJS 1.7 (модель флажка теперь допускает только логические значения, а все остальное преобразуется в логические), теперь я нашел решение, которое работает до версии 1.8: спасибо @The.Bear за базу .
Чтобы использовать его, просто включите
<tristate label="someOptionalText" ng-model="yourVariableToBindTo" />
и соответствующую директиву.