XT_Nova
XT_Nova

Reputation: 1170

What's a good way of adding and remove object details to an array when a checkbox is checked or unchecked using AngularJS?

I have an API which takes objects e.g.

{ 
   'title': 'Some', 
   'desc': 'thing', 
   'environments': '[
           {'id': 1}, 
           {'id': 2}
    ]
}

To add new entries i have a form for setting the title and the description for the object i'm going to pass to my API:

<form class="form horizontal"role="form" ng-submit="vm.submitForm()">

        <label for="Title">Title</label>
        <input  class="form-control"
                id="Title" 
                type="text" 
                ng-model="vm.myObj.title" 
                placeholder="Title"/>

        <label for="Desc">Description</label>
        <input  class="form-control"
                id="Desc" 
                type="text" 
                ng-model="vm.myObj.desc" 
                placeholder="Description"/>

        <div class="checkbox" ng-repeat="env in vm.availableEnvs">
            <label>
                <input type="checkbox" /> 
                {{env.label}}
            </label>
        </div>

        <hr />

        <button>Submit</button>
</form>

In the form you probably saw that i had a ng-repeatthat repeats over an array of environment objects:

this.environments = [
        { id: 1, label: "US" },
        { id: 2, label: "EU" },
        { id: 3, label: "ASIA" },
        { id: 4, label: "AFRICA" }
    ];

Since the API need to get an array of: {id: x } objects, i was wondering if anyone has a good way for adding (and removing) object details to myObj.environmentsarray when you check or un-check a checkbox?

My .js code: Link to JSFiddle Here

(function(){
angular
    .module('myApp', [])
    .controller('MyCtrl', MyCtrl)
    .service('EnvService', EnvService);


MyCtrl.$inject = ['EnvService'];
function MyCtrl(EnvService) {
    var vm = this;
    vm.availableEnvs = EnvService.getAvailableEnvironments();

    vm.myObj = { 
        title: '', 
        desc: '',
        environments: [] 
    };

    vm.submitForm = submitForm;

    function submitForm() {
        //Call a service that handles $http and makes a POST with myObj                        
    }

}

function EnvService() {
    this.environments = [
        { id: 1, label: "US" },
        { id: 2, label: "EU" },
        { id: 3, label: "ASIA" },
        { id: 4, label: "AFRICA" }
    ];

    this.getAvailableEnvironments = function() {
        return this.environments;   
    }
}
})();

Upvotes: 0

Views: 624

Answers (2)

Shadow3188
Shadow3188

Reputation: 265

I would add an ng-click and use the $event arg to processes what state that checkbox is beign set to(true or false)

Then you pass that and the corresponding id to an update function which will update the vm.myObj.environments array accordingly without the need of a temp array. A deselect would remove and a select would add.

<input type="checkbox" ng-click="vm.toggleEnv($event, env.id)" />{{env.label}}</label>

and here would be the updated functions:

    vm.toggleEnv = function ($event, id) {
        //Get the checkbox that was clicked
        var chbx = $event.target;

        //Depending on the status, different actions should be taken
        vm.updateEnv(chbx.checked, id);
    };

    vm.updateEnv = function (isChecked, envId) {
        //If the Deselect
        if (!isChecked) {
            for (var i = 0; i < vm.myObj.environments.length; i++) {
                //Check to see if the id's match
                if (vm.myObj.environments[i].id == envId) {
                    //Remove the Item
                    vm.myObj.environments.splice(i, 1);
                    break; //Exit the loop
                }
            }
        } else {
            //Add the item
            vm.myObj.environments.push({
                id: envId
            });
        }
    };

Here is a forked fiddle: http://jsfiddle.net/xe9aL1ch/

Upvotes: 0

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40296

What I do in such cases is outlined as follows:

  1. Make an intermediate array, holding the set memberships, i.e. intermediateArray[i] is true if mainArray[i] is included in the post data. Obviously bind intermediateArray[i] to the i-th checkbox.
  2. Do a $watchCollection on the intermediateArray and set the target collection accordingly.

The forked fiddle: http://jsfiddle.net/Lz23r2hd/

(In the fiddle I also changed the service to return a promise - I believe it is a best practice, but non-essential for this answer.)

Upvotes: 2

Related Questions