Search code examples
angularjsangularjs-ng-modelangularjs-ng-changeangularjs-ng-checked

ng-checked and ng-change radio button not work together - angularjs


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

js

angular.module("sampleapp", []).controller('samplecontroller', function($scope,$rootScope) {
  $scope.radii = [
    {id:.25, checked:false, name:"1/4 Mile"},
    {id:.5, checked:false, name:"1/2 Mile"},
    {id:1, checked:false, name:"1 Mile"},
    {id:2, checked:true, name:"2 Mile"},
    {id:3, checked:false, name:"3 Mile"},
    {id:4, checked:false, name:"4 Mile"},
    {id:5, checked:false, name:"5 Mile"}
];

$scope.handleRadioClick = function(){
    alert();

};
});

and html

          <div class="radio">
            <label>
              <input type="radio" name="radius"

                   ng-change="handleRadioClick()"
                   ng-checked="radius.checked">

              {{radius.name}}

            </label>
          </div>

      </li>

Notice "2 Mile" radio input is checked based on the radii scope structure. Why doesn't the ng-change trigger the function?

If I add ng-model, the function triggers but the ng-checked does not work.


Solution

  • This is because you are not using ng-model:

    FORKED PLUNKER

    <div class="radio" ng-repeat="radius in radii" id="selectradius-{{radius.id}}">
      <label>
        <input type="radio" name="radius"
    
             ng-change="handleRadioClick(selectedRadius)"
             ng-model="radius.checked">
    
        {{radius.name}}
    
      </label>
    </div>
    

    UPDATE:

    I'm sorry that I didn't notice that you wanted to have a default radio button checked, if that is the case then the approach you're taking is incorrect. You must consider the model as non-individual parts in a group of radio buttons but as a whole, they are supposed to be one value instead. You don't have to use ng-repeat's radio scope variable instead use another ng-model as the selectedRadius model. Your input radio needs to have a value, and in this case we'll use ng-value to determine the current value of the model.

    UPDATED PLUNKER [2014 September]

    JAVASCRIPT

    Controller

      $scope.radii = [
        {id:.25, name:"1/4 Mile"},
        {id:.5, name:"1/2 Mile"},
        {id:1, name:"1 Mile"},
        {id:2, name:"2 Mile"},
        {id:3, name:"3 Mile"},
        {id:4, name:"4 Mile"},
        {id:5, name:"5 Mile"}
      ];
    
      // selected value is {id:2, name:"2 Mile"}
      $scope.selectedRadius = $scope.radii[3];
    

    HTML

    <div class="radio" ng-repeat="radius in radii" id="selectradius-{{radius.id}}">
      <label>
        <input type="radio" name="radius"
    
             ng-change="handleRadioClick(radius)"
             ng-model="selectedRadius"
             ng-value="radius">
    
        {{radius.name}}
    
      </label>
    </div>
    

    UPDATED PLUNKER [2015 January]

    dcz.switcher's problem below suggested that the solution above does not trigger the ng-change event handler when a radio button is reselected. The main problem was that the ng-model was referring to the ng-repeat's scope and not to the controller's scope from the second change. To solve this problem you can use the $parent property. An alternative would be to use controllerAs alias and use the alias itself to access your controller's property. To understand more about scopes in AngularJS, I suggest you read more about it in here.

    HTML

    <div class="radio" ng-repeat="radius in radii" id="selectradius-{{radius.id}}">
      <label>
        <input type="radio" name="radius"
    
             ng-change="handleRadioClick($parent.selectedRadius)"
             ng-model="$parent.selectedRadius"
             ng-value="radius">
    
        {{radius.name}}
    
      </label>
    </div>