Checkbox not binding to scope in angularjs
Asked Answered
M

5

63

I am trying to bind a checkbox to scope using ng-model. The checkbox's initial state corresponds to the scope model just fine, but when I check/uncheck the checkbox, the model does not change. Some things to note is that the template is dynamically loaded at runtime using ng-include

app.controller "OrdersController", ($scope, $http, $location, $state, $stateParams, Order) ->

  $scope.billing_is_shipping = false
  $scope.bind_billing_to_shipping = ->
    console.log $scope.billing_is_shipping


<input type="checkbox" ng-model="billing_is_shipping"/>

When I check the box the console logs false, when I uncheck the box, the console again logs false. I also have an order model on the scope, and if I change the checkbox's model to be order.billing_is_shipping, it works fine

Mccain answered 5/9, 2013 at 17:23 Comment(0)
D
161

I struggled with this problem for a while. What worked was to bind the input to an object instead of a primitive.

<!-- Partial -->
<input type="checkbox" ng-model="someObject.someProperty"> Check Me!

// Controller
$scope.someObject.someProperty = false
Defame answered 29/5, 2014 at 22:15 Comment(7)
I had the same problem, and this fixed it. I wonder why primitives weren't working (as they do in the official docs)...Bates
Thank you for this!! Not sure why this doesn't work with a primitive, could this just be a bug in Angular?Crosseye
Guys, this answer a little be a hack. I suggest you read @zsong asnwerLuckey
@Luckey nope, that's not the issue, one might notice if his variables are elsewhere.. Also, I'm back on this page because this keeps happening: does anyone have any insight on the issue? Getting frustratedWestbrook
Hi, I used the same way and the value of the model gets updated in view. But the value is not being reflected in controller. It always shows false in controller. Pls suggest what could be causing this.Lolanthe
Thank you buddy, one more thing to learn with "The best practice is to never bind directly to a variable on the scope in an ng-model, this is also known as always including a "dot" in your ngmodel"Messaline
This worked for me too!, we also need to define the object in controller too. like $scope.someObject ={};Umbria
A
27

If the template is loaded using ng-include, you need to use $parent to access the model defined in the parent scope since ng-include if you want to update by clicking on the checkbox.

<div ng-app ng-controller="Ctrl">
    <div ng-include src="'template.html'"></div>
</div>

<script type="text/ng-template" id="template.html">
    <input type="checkbox" ng-model="$parent.billing_is_shipping" ng-change="checked()"/>
</script>

function Ctrl($scope) {
    $scope.billing_is_shipping = true;

    $scope.checked = function(){
        console.log($scope.billing_is_shipping);
    }
}

DEMO

Adduct answered 5/9, 2013 at 17:28 Comment(12)
Also, I have bound several other properties in the same template without using $parent and it works for thoseMccain
If I initialize billing_is_shipping as true, the checkbox is initially checked, so it is getting the right value, but just not binding it on that checkbox for some reasonMccain
Another thing I tried is duplicating the checkboxes and I discovered that checking one checks the otherMccain
@Chris I created a demo for you. If you want to update the model from the inner scope, you do need $parent for that.Adduct
I tried that and it didn't work, see my above comments and see if anything else occurs to you?Mccain
I also have an order model on the scope, and if I change the checkbox's model to be order.billing_is_shipping, it works fineMccain
@Mccain Can you just open the demo I created for you and compare it with your code?Adduct
@Chris Then there got be something else in your code is funky since the demo work fine without any problem.Adduct
I think the strangest thing is that it will bind to order.billing_is_shipping just fine and other bindings in the same template bind to $scope properties just fine as well, without using $parentMccain
@Chris The best way I can help you is if you can update the fiddle and show the rest of your code.Adduct
To explain, you are correct, including creates child scope which prototypically inherits from parent. $parent.billing_is_shipping wasnt working because I had ng-include nested in another ng-include. I suspect $parent.$parent.billing_is_shipping might have worked but i moved all my views into the first ng-include so $parent.billing_is_shipping works correctly nowMccain
And solved my problem too, but why this suits for me while the real answer doesn't, just why? There must be some explanation.Exhalation
P
9

In my directive (in the link function) I had created scope variable success like this:

link: function(scope, element, attrs) {
            "use strict";

            scope.success = false;

And in the scope template included input tag like:

<input type="checkbox" ng-model="success">

This did not work.

In the end I changed my scope variable to look like this:

link: function(scope, element, attrs) {
            "use strict";

            scope.outcome = {
                success : false
            };

And my input tag to look like this:

<input type="checkbox" ng-model="outcome.success">

It now works as expected. I knew an explanation for this, but forgot, maybe someone will fill it in for me. :)

Phratry answered 6/4, 2014 at 9:53 Comment(1)
Voted up! I've been struggling with the same issue (we're both using directives) for almost two days now. This saved my life and my deadline. Thank you for sharing this! =o)Pyromorphite
N
9

Expanding on Matt's answer, please see this Egghead.io video that addresses this very issue and provides an explanation for: Why binding properties directly to $scope can cause issues

see: https://groups.google.com/forum/#!topic/angular/7Nd_me5YrHU

Usually this is due to another directive in-between your ng-controller and your input that is creating a new scope. When the select writes out it value, it will write it up to the most recent scope, so it would write it to this scope rather than the parent that is further away.

The best practice is to never bind directly to a variable on the scope in an ng-model, this is also known as always including a "dot" in your ngmodel.

Narcose answered 22/3, 2016 at 23:35 Comment(3)
This answer relies completely on external links. Should they ever become invalid, your answer would become useless. So please edit it and add at least a summary of what can be found there. Thank you!Carn
@FabioTurati how prescient! the youtube video is inoperable now!Gerhart
@Gerhart Really? It works for me. Anyway it isn't just my idea, it's a policy of SO's, and the reason is that at such a large scale (there are millions of answers here!) this problem is bound to happen, therefore we need to take countermeasures.Carn
F
0

This worked for me, as I was using 1 and 0 instead of true and false:

<input id="dialogIsInternal" type="checkbox" ng-model="dialog.is_internal" ng-true-value="1" ng-false-value="0" />
Frig answered 23/2, 2024 at 23:47 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.