ng-checked and ng-change radio button not work together - angularjs
Asked Answered
B

4

11

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.

Bitten answered 23/8, 2014 at 0:17 Comment(0)
S
12

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>
Soembawa answered 23/8, 2014 at 2:29 Comment(2)
Although, this does call my function, the default radio is not checked anymore. So I'm giving up on this because apparently there is no way to do both things that I want. I just hope everyone here understands my simple request and understands that there is no solution.Bitten
Plus one for using plural radii :-)Dictator
A
4

Use default values and everything will work like a charm, no need to $watch scope or anything... and Yes you need ng-model

  • ng-model - does all work
  • ng-checked - makes sure you have CHECKED attribute present
  • ng-change - will trigger your function on-Change

HTML example:

<input type="checkbox" 
    ng-model="row.active"
    ng-checked="row.active"
    ng-true-value="1"
    ng-false-value="0"
    ng-change="update(row)"
/>
<!-- test -->
{{ row.active }}

JS optional:

$scope.update = function(row) {
    console.log('row.active');
}
Acquittal answered 23/4, 2015 at 16:37 Comment(2)
Seems to make logical sense, but in angular docs for ng-checked it says: "Note that this directive should not be used together with ngModel, as this can lead to unexpected behavior."Merwin
ngModel and ngChecked are not meant to be used together. See AngularJS: ng-model not binding to ng-checked for checkboxes.Ethelstan
S
2

This is because ng-change requires ngModel to be present.

Hope this helps. Cheers!

Sanburn answered 23/8, 2014 at 2:36 Comment(0)
E
0

The ng-change directive requires the ng-model directive to be present.

From the Docs:

ngChange

Note, this directive requires ngModel to be present.

— AngularJS ng-change Directive API Reference


The ng-model and ng-checked directives should not be used together

From the Docs:

ngChecked

Sets the checked attribute on the element, if the expression inside ngChecked is truthy.

Note that this directive should not be used together with ngModel, as this can lead to unexpected behavior.

— AngularJS ng-checked Directive API Reference

Instead set the desired initial value from the controller.

For more information, see

Ethelstan answered 6/7, 2018 at 17:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.