Search code examples
javascriptangularjscheckboxtri-state-logic

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


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.


Solution

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