0

I was given a requirement that all radio buttons across our site need to be unselectable. I can manage to do this with a function hardcoded to that set of radio buttons. But I would prefer to have a generic one so I don't have to add the same lines of code over and over.

Here's is my attempt to create a generic one. It seems to almost work in that it detects when the radiobutton should be cleared (I logged in the console) but it does not actually clear anything.

$scope.RadioCheckUncheck = function (RadioModel, event) {
  if (RadioModel === event.target.value) {
    console.log('looks like you clicked this already')
    RadioModel = null;
  }
}

and HTML

ng-click="RadioCheckUncheck(myModelName, $event)"

http://plnkr.co/edit/HcMfXWTtIRT9WThxE3c5?p=preview

Here is a similar version that works, but it's hardcoded.

http://plnkr.co/edit/00XCKeiIJJeFj96yARjC?p=preview

  • What about $timeout(function() { $('.anycommonclass').attr('checked', false).trigger('change'); }); – Joao Polo Sep 18 '15 at 20:05
  • Well, here's [How to unselect a radio button](http://stackoverflow.com/q/10876953/4320665). Then you'd just have to figure out a good way to make all the radio buttons unselectable. I'd personally go with applying a custom attribute directive on specific radio inputs. – ryanyuyu Sep 18 '15 at 20:21

3 Answers3

1

Inside your RadioCheckUncheck method, the RadioModel parameter is just a string, not a reference to the $scope field, so setting it to null will not have the desired effect. You could instead pass the "key" to your FavoriteThingies dictionary and set it to null using that.

HTML:

<input type="radio" name="my_favorite" ng-value="'Tom'" ng-model="FavoriteThingies.FavoriteCharacter" ng-click="RadioCheckUncheck('FavoriteCharacter', $event)">Tom
<input type="radio" name="my_favorite" ng-value="'Jerry'" ng-model="FavoriteThingies.FavoriteCharacter" ng-click="RadioCheckUncheck('FavoriteCharacter', $event)">Jerry

<input type="radio" name="my_favorite_fruit" ng-value="'Orange'" ng-model="FavoriteThingies.FavoriteFruit" ng-click="RadioCheckUncheck('FavoriteFruit', $event)">Orange
<input type="radio" name="my_favorite_fruit" ng-value="'Apple'" ng-model="FavoriteThingies.FavoriteFruit" ng-click="RadioCheckUncheck('FavoriteFruit', $event)">Apple

JavaScript:

var myApp = angular.module('myApp', []);

myApp.controller('RadioController', function ($scope) {
    $scope.FavoriteThingies = {};
    $scope.RadioCheckUncheck = function (key, event) {
      if ($scope.FavoriteThingies[key] === event.target.value) {
        console.log('looks like you clicked this already')
        $scope.FavoriteThingies[key] = null;
      }
    }
});

An updated version is here: http://plnkr.co/edit/U0aQEfe6WBTfsu8MPsBQ?p=info.

Drew Gaynor
  • 8,292
  • 5
  • 40
  • 53
1

What I would do in your case is create a directive for this (won't get anything more reusable than this)

Something like

myApp.directive('uncheckable', function(){
  return {
    scope: {
      val: '=ngModel'
    },
    link: function(scope, element, attrs){
      element.bind('click', function(){
        if(scope.val) scope.val = null;
      })
    }
  }
})

and then just use it like:

<input uncheckable type="radio" name="Tom" ng-value="'Tom'" ng-model="myModel" />

Here is a plnkr http://plnkr.co/edit/Ts2a6z3zbEyjlbXzaAYC?p=preview

You can even be more elaborate playing with ngModelController instead of binding to ngModel (which has the exact same effect, but is more powerful) by doing something like:

myApp.directive('uncheckable', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModelController) {
      if(!ngModelController) return; //do nothing if not binded
      element.bind('click', function() {
        if (ngModelController.$modelValue) {
          ngModelController.$setViewValue(null);
          ngModelController.$render();
        }
      })
    }
  }
})

check it here http://plnkr.co/edit/IrvfZq?p=preview

masimplo
  • 3,674
  • 2
  • 30
  • 47
0

Seems like you want a directive, so you can easily re-use this functionality. I've updated the plunkr here:

http://plnkr.co/edit/yQv4vZwX1Tf2uhPy7Kff?p=preview

... but here's the meat for convenience:

myApp.directive('unselectable', [function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      clickCount = 0;
      element.on('click', function() {
        clickCount++;
        if (element[0].checked && clickCount > 1) {
          element[0].checked = false;
          clickCount = 0;
        }
      });
    }
  }
}]);

Then just add the directive to the radio elements:

<input unselectable type="radio" name="my_favorite" ng-value="'Tom'" ng-model="FavoriteThingies.FavoriteCharacter">
Fishz
  • 465
  • 2
  • 12