Helen Che
Helen Che

Reputation: 2011

How to bind data depending on if checkbox is checked?

Just getting started on Angular, I'm using checkboxes to determine which parameters get sent during a get request (this is my attempt):

<input type="checkbox" ng-click="submit('color[]', 'red')"/>
<input type="checkbox" ng-click="submit('color[]', 'green')" checked/>
<input type="checkbox" ng-click="submit('color[]', 'blue')"/>

I have a variable $scope.params that stores the parameters of my http get request. My submit function is very simple:

$scope.submit = function (attribute, value) {
  $scope.params[attribute] = value;
};

It simply adds color[] to the params object. Unlike radio, checkbox values can be stored as arrays and submitted as such: api?color[]=red&color[]=green as my backend is PHP this is the preferred format. However my submit function simply overwrites this every time. I'm not sure how to store multiple params with the same "key".

My other problem is that ng-click is not appropriate for this task as it doesn't take in the current state of the checkbox. Notice that my green checkbox is initially loaded as checked. Is there a way to bind this to my $scope.params object?

Ideally I want to implement something like:

$scope.params = {
  "color[]" = ['red', 'green', 'blue']
};

According to Semicolon's answer below, I can use:

<input type="checkbox" ng-model="params.colors[]" ng-true-value="'red'"/>
<input type="checkbox" ng-model="params.colors[]" ng-true-value="'blue'"/>
<input type="checkbox" ng-model="params.colors[]" ng-true-value="'green'"/>

But naming anything with "[]" just breaks the code.

Upvotes: 1

Views: 3073

Answers (1)

Semicolon
Semicolon

Reputation: 7413

Checkboxes, like all input elements, are supported with ng-model. This core directive is a cousin of ng-bind. It says "the state of this element represents this model". Its behavior is determined by the input type. In the case of a checkbox, the value you are modeling is going to be boolean typically, since a checkbox is fundamentally a "boolean" input (checked/unchecked == true/false).

<input type="checkbox" ng-model="colors.red"/>

In the controller function:

$scope.colors = {
    red: false,
    green: true,
    blue: false
};

Actually you can map checked/unchecked to non-boolean values too, using ng-true-value and ng-false-value. You can read more about these and other options for ng-model with checkboxes in the Angular docs:

https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D

The core difference between ng-bind and ng-model is that the former is unidirectional (just a view) and the latter is bidirectional (the element can be used to change the model).

A more general answer regarding the premise of MVC in Angular:

In the example in your question, you were using a jQuery-like solution to try to achieve binding between the view and controller. This is really not ideal. Only bind a function to click events when you are specifically interested in having something take place "on click".

What if a user uses the tab key and the spacebar to check the box? The model would not get updated.

Or let's say you want to change the value in the model somewhere else -- maybe you have a "reset" button that returns them to the original values. The view would not get updated.

If the connection between the view and the model is all through "actions" it is easy for them to be out of sync. You'd have to make sure you handled every possible way the user could interact with the element and each time you change the data programmatically you would need to push the change to the view explicitly. But using ng-model and ng-bind lets you keep them synced no matter where the model is changed or how the user interacts. Really this is the main point of Angular.

Upvotes: 3

Related Questions