1

Trying to do something I thought is pretty simple but it's turning out to be pretty annoying. I'm just trying to have a function that runs when you click on a checkbox using the ng-checked directive.

This is the HTML:

    <div class="form-group">
        <label class="col-sm-2 control-label">Make Payment Optional</label>
        <div class="col-sm-4 center-checkbox">
            <input type="checkbox"
                   class="center-checkbox"
                   ng-model="formData.optionalPayment"
                   ng-checked="optionalPaymentCheckbox();"
                   validate-servererror="featured"/>
        </div>
    </div>

And this is the Angular:

if($scope.formData.optionalPayment === undefined) {
  $scope.formData.optionalPayment = TournamentConst.PAYMENT.OPTIONAL;
}

(This check is just for when I load the page for the first time.)

$scope.optionalPaymentCheckbox = function () {
  if($scope.formData.optionalPayment === TournamentConst.PAYMENT.OPTIONAL) {
    $scope.formData.optionalPayment = TournamentConst.PAYMENT.MANDATORY;
  } else {
    $scope.formData.optionalPayment = TournamentConst.PAYMENT.OPTIONAL;
  }
};

When I load the page, this ng-checked function runs infinitely. Is there something about the ng-checked directive I don't know, or some minor detail or forgot? Thanks in advance.

amacdonald
  • 157
  • 15
  • 1
    Well, yes. It calls it, it changes the value of optionalPayment, then it calls it again as to see if the model is now stable, and that changes it back to its revious value, etc. etc. I fail to understand what you want to achieve. You're not even returning anything from the method. What do you want to do? – JB Nizet Jan 10 '17 at 23:14
  • I'm just trying to make a checkbox that is TournamentConst.PAYMENT.OPTIONAL when it's not checked and TournamentConst.PAYMENT.MANDATORY when it is checked. – amacdonald Jan 10 '17 at 23:15
  • That's what ng-true-value and ng-false-value are for. Not ng-checked. https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D – JB Nizet Jan 10 '17 at 23:16

1 Answers1

3

You are misunderstanding the intention of ng-checked. What you think it does is "execute this expression when the checkbox is checked" - an event handler directive.

What it actually does is set the checked property based on the expression. This means it sets up a watch on the expression and evaluates it every digest. If the value changes, it sets or unsets the checked property accordingly.

In fact, the documentation for ng-checked says this:

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

As @JB Nizet correctly pointed out, you can achieve the desired effect in your particular case by using ng-true-value and ng-false-value and removing ng-checked altogether.

So your HTML becomes:

<div class="form-group">
    <label class="col-sm-2 control-label">Make Payment Optional</label>
    <div class="col-sm-4 center-checkbox">
        <input type="checkbox"
               class="center-checkbox"
               ng-model="formData.optionalPayment"
               ng-true-value="TournamentConst.PAYMENT.MANDATORY"
               ng-false-value="TournamentConst.PAYMENT.OPTIONAL"
               validate-servererror="featured"/>
    </div>
</div>

Then, in your controller, populate your TournamentConst object in the scope, so the template can see it:

$scope.TournamentConst = TournamentConst;

(or you can just populate the bits you need)

Finally, get rid of the whole $scope.optionalPaymentCheckbox function. You will still need the code to set the default value, though.

One last thing: It is confusing that the property is called optionalPayment, when it is really more like paymentType, but that is not related to the current problem.

GregL
  • 37,147
  • 8
  • 62
  • 67
  • 2
    Since the function changes the ng-model of the checkobx itself, ng-change is not the right solution either. All he/she needs is ng-true-value and ng-false-value (and ng-model, of course). But your explanation is correct. – JB Nizet Jan 10 '17 at 23:20
  • Good to know! Thank you both for the explanation. I'm actually trying ng-change now and it's not working either. I am setting the model to a specific value on the page load, but when I click on the checkbox it tells me that value is just true instead of the actual value. I'll try ng-true-value and ng-false value. – amacdonald Jan 10 '17 at 23:24
  • 1
    @JBNizet You should post this as an answer, it is indeed the correct solution. `ng-change` is not needed. – GregL Jan 10 '17 at 23:25
  • 1
    Feel free to amend your answer with my suggestion. It already has a nice explanation. – JB Nizet Jan 10 '17 at 23:26