MChan
MChan

Reputation: 7162

AngularJS moving items between two select list

I am trying to move items between two select lists using the code below, but items are not moved from the availableClients list to selectedClients lists, so can someone please check the code below and let me know what I am missing here? Thanks

  <div ng-app>
  <div ng-controller="testCtrl">

            <label for="aclients">Available Clients</label>                                
            <select size="5" multiple ng-model="available" ng-options="client.id as client.Name for client in clientsList" style="width: 400px"></select>         

            <input id="moveright" type="button" value="Add Client" ng-click="moveItem(available[0], availableclients,selectedclients)" />
            <input id="moverightall" type="button" value="Add All Clients" ng-click="moveAll(availableclients,selectedclients)" />
            <input id="move left" type="button" value="Remove Client" ng-click="moveItem(selected[0], selectedclients,availableclients)" />    
            <input id="moveleftall" type="button" value="Remove All Clients" ng-click="moveAll(availableclients,selectedclients)" />

            <label for="sclients">Selected Clients</label>                                                    
            <select size="5" multiple ng-model="selected" ng-options="client.id as client.Name for client in selectedclients" style="width: 400px"></select>
            <div>Selected Clients IDs: {{selectedclients}}</div>           

  </div>
  </div>

Controller:

  app.controller('testCtrl',
        function testCtrl($scope, clientsService){


   $scope.clientsList = clientsService.getClientsList().then(
            function(response){
               $scope.clientsList = response;
            },
            function(status){
               console.log(status);
            }
    );              

    $scope.moveItem = function(item, from, to) {

        console.log('Move item   Item: '+item+' From:: '+from+' To:: '+to);
        //Here from is returned as blank and to as undefined

        var idx=from.indexOf(item);
        if (idx != -1) {
            from.splice(idx, 1);
            to.push(item);      
        }
    };
    $scope.moveAll = function(from, to) {

        console.log('Move all  From:: '+from+' To:: '+to);
        //Here from is returned as blank and to as undefined

        angular.forEach(from, function(item) {
            to.push(item);
        });
        from.length = 0;
    };                

    $scope.availableclients = [];                
    $scope.selectedclients = [];                                


  });  

Upvotes: 7

Views: 16612

Answers (2)

GregJF
GregJF

Reputation: 466

In regard to my comment/question. I actually found an answer. So for those that come here and have the same issue, here is what I found.

When moving a item from one SELECT list to another SELECT list, the angular model on the source list can get "lost". To avoid this, the changed to each list must be done in separate $apply function call. Here is a cut down example from within in the event handler

onClickRight = function (item, from, to) {
    var self = this;
    var selecteditem = angular.copy(item);
    self.$timeout(function () {
        self.scope.$apply(function () {                
            for (var idx = 0; idx < from.length; idx++) {
                if (from[idx].value == item.value && from[idx].displayValue == item.displayValue) {
                   item.length = 0;
                   from.splice(idx, 1);
                   break;
                 }          
                };
            });
        }, 200);
        self.$timeout(function () {
            self.scope.$apply(function () {
                to.push(selecteditem); 
            });
        }, 300);
    };

The 'item' is cloned with angular.copy so it can be used in the second angular $apply My options have a 2 properties: value and displayValue I also assign $timeout and $scope to the 'self' variable in the directive's constructor. Hope this helps

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691765

There are several small problems in your template:

  • You're moving objects from availableclients to selectedclients, but the first select displays options from clientsList, and not from availableclients
  • You're moving IDs rather than objects. Your ng-options should simply be

    client as client.name for client in availableclients
    
  • Your remove all button moves from available to selected, instead of moving from selected to available.

Here is a working plunkr: http://plnkr.co/edit/RYEmpkBjQStoCfgpWPEK?p=preview

<label for="aclients">Available Clients</label>                                
<select size="5" multiple ng-model="available" ng-options="client as client.name for client in availableclients" style="width: 400px"></select>         

<input id="moveright" type="button" value="Add Client" ng-click="moveItem(available[0], availableclients,selectedclients)" />
<input id="moverightall" type="button" value="Add All Clients" ng-click="moveAll(availableclients,selectedclients)" />
<input id="move left" type="button" value="Remove Client" ng-click="moveItem(selected[0], selectedclients,availableclients)" />    
<input id="moveleftall" type="button" value="Remove All Clients" ng-click="moveAll(selectedclients,availableclients)" />

<label for="sclients">Selected Clients</label>                                                    
<select size="5" multiple ng-model="selected" ng-options="client as client.name for client in selectedclients" style="width: 400px"></select>

Upvotes: 15

Related Questions