What's the best way to implement a single tri-state checkbox within angularjs?

て烟熏妆下的殇ゞ 提交于 2019-12-18 15:28:32

问题


Is there a simple way to place a single tri-state checkbox on a web-page and bind it to a boolean model so the latter can take true, false or null values?

The closest solution I found so far is http://jsfiddle.net/HB7LU/454/ but it has a flaw when setting up an initial view state (as there is no way to get a model value during first rendering). Any other suggestions deal with multiple child checkboxes and solves the problem by watching on them.


回答1:


http://jsfiddle.net/xJhEG/ I made it in a commercial project. Tristates are true, false, null (not "unknown")

.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);
        });
      }
    };
  }])



回答2:


Here my Fiddle, starting from TruongSinh and changing

http://jsfiddle.net/xJhEG/25/

without

var truthy = true;
var falsy = false;
var nully = null;



回答3:


You have take advantage of the indeterminate state of <input type="checkbox">.

MDN web docs: There exists an indeterminate state of checkboxes, one in which it is not checked or unchecked, but undetermined. This is set using the HTMLInputElement object's indeterminate property via JavaScript (it cannot be set using an HTML attribute).

PLUNKER: TRISTATE DIRECTIVE

HTML

<label>
    <input type="checkbox" ng-model="state" indeterminate /> {{state}}
</label>

DIRECTIVE

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);
        });
      }
    }
  };
});



回答4:


I've created directive, which you can use. Three-state checkbox AngularJS Directive on GitHub

There is also a post, how it was built: Creating Angular Directive "Three-state checkbox

You can try a DEMO

And the directive looks like that:

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);
            }
        };
    }]);


来源:https://stackoverflow.com/questions/21347384/whats-the-best-way-to-implement-a-single-tri-state-checkbox-within-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!