Search code examples
angularjsangularjs-ng-repeatbootstrap-multiselect

Angular JS ng-model is not working properly for array of array


My requirement

  1. I should have two multiselect comboboxes
  2. Should be able to select multiple value
  3. Based on the selected values from combobox1 the second combobox should should populate the values

for that I'm using the AngularJs and Multiselect.Js

I'm able to achieve 1 and 2.

For point 3. I'm finding it difficult to populate the data based on the selected values from combobox 1

Note: when I select a single role the related workers information is displayed in the second combobox, but when Iselect the multiple roles it doesn't work.

I believe this part of the code doesn't work for multiple array

 options="c.WorkerName for c in selectedRoles.workers"

if you specific the array index then it will work and only select the workers for that index, but when multiple values selected below code isn't not working.

 options="c.WorkerName for c in selectedRoles[0].workers"

reference from http://plnkr.co/edit/xWvfWYjaW7TThKZONkv5?p=preview

My html code is below :

    <!DOCTYPE html>
    <html ng-app="plunker">
    <head>
        <meta charset="utf-8" />
        <title>AngularJS Plunker</title>
        <link data-require="[email protected]" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
        <script>document.write('<base href="' + document.location + '" />');</script>
        <link rel="stylesheet" href="style.css" />
        <script data-require="[email protected]" src="angular.min.js" data-semver="1.1.5"></script>
        <script src="app.js"></script>
        <script src="multiselect.js"></script>
    </head>

<body ng-controller="MainCtrl">
    <h1>Example</h1>
    Multi select:

    <multiselect class="input-xlarge" multiple="true" header="select roles"
        ng-model="selectedRoles"
        options="c.roleName for c in roles"
        change="selected()"
        template-url="multiselect.tmpl.html">
    </multiselect>

    <div class="well well-small">
        {{selectedRoles}}
    </div> 

    <multiselect class="input-xlarge" multiple="true" header="select workers"
        ng-model="selectedWorkers"
        options="c.WorkerName for c in selectedRoles.workers"
        change="selected()"
        template-url="multiselect.tmpl.html">
         </multiselect>

    <div class="well well-small">
        {{selectedWorkers}}
    </div>
</body>

</html>

And Javascript and JSON data:

Combobox 1 : Will display the "roleName" from the "$scope.roles", and Combobox 2: Should display the workers, from the selected "rolename" (from comboxbox1)

var app = angular.module('plunker', ['ui.multiselect']);

app.controller('MainCtrl', function ($scope) 
{
    $scope.name = 'multiselect';

$scope.roles =
    [
      {
          "roleGuid": "7b48aa01-7dad-4640-abcb-04d8e2666160",
          "roleName": "Electric",
          "workers": [
            {
                "WorkerName": "Bond, James",
                "WorkerGuid": "dac36324-2f7e-4dca-9e3a-2a9d8ac419ee"
            },
            {
                "WorkerName": "Story, 843",
                "WorkerGuid": "85a234a9-3d86-41c2-832c-7a3d40977e88"
            },
            {
                "WorkerName": "Test, SAT124",
                "WorkerGuid": "135149fb-b34e-4270-82f6-3488bd59a598"
            },
            {
                "WorkerName": "Test, SAT-18_1",
                "WorkerGuid": "15bf6b49-5405-41a5-8473-cfe389bbb1ff"
            },
            {
                "WorkerName": "Verma, Sunil",
                "WorkerGuid": "c785f1a1-34e3-4687-9df1-961331b62e0e"
            },
            {
                "WorkerName": "Y, Venkata",
                "WorkerGuid": "ae18e61b-340e-4f27-92ac-c701026242c9"
            },
            {
                "WorkerName": "Yadalla, Venkata",
                "WorkerGuid": "a9142270-e084-4c38-8e9f-448e647c8841"
            }
          ]
      },
      {
          "roleGuid": "e182d217-7806-4227-905e-ca64c7ac9b76",
          "roleName": "General Employee",
          "workers": [
            {
                "WorkerName": "1111, hen",
                "WorkerGuid": "93ef8fc9-6fcd-4d26-afca-7ba01968f9ab"
            },
            {
                "WorkerName": "Giri, Ashok",
                "WorkerGuid": "2e0c7ba6-3a57-4970-a30c-68fba448492b"
            }
          ]
      },
      {
          "roleGuid": "270ad5e9-370a-43cc-927c-c9b275037447",
          "roleName": "Inspection Worker",
          "workers": [
            {
                "WorkerName": "Test, pals3",
                "WorkerGuid": "d447cd4a-9f19-463f-880b-9e09e830f9fd"
            }
          ]
      }
    ];
$scope.selectedRoles = [];
$scope.selectedWorkers = [];

});

And multiselect template

<div class="dropdown">
  <button class="btn" ng-click="toggleSelect()" ng-disabled="disabled" ng-class="{'error': !valid()}">
    <span class="pull-left">{{header}}</span>
    <span class="caret pull-right"></span>
  </button>
  <ul class="dropdown-menu">
    <li>
      <input class="input-block-level" type="text" ng-model="searchText.label" autofocus="autofocus" placeholder="Filter" />
    </li>
    <li ng-show="multiple">
      <button class="btn-link btn-small" ng-click="checkAll()"><i class="icon-ok"></i> Check all</button>
      <button class="btn-link btn-small" ng-click="uncheckAll()"><i class="icon-remove"></i> Uncheck all</button>
    </li>
    <li ng-repeat="i in items | filter:searchText">
      <a ng-click="select(i); focus()">
        <i ng-class="{'icon-ok': i.checked, 'icon-empty': !i.checked}"></i>{{i.label}}</a>
    </li>
  </ul>
</div>

Solution

  • One way to do this would be to write a function to generate a list of workers from the selected roles. Whenever the selected roles changes, call this function to update a list of selectable workers.

    This might put you on the right path:

    http://plnkr.co/edit/UrCJeCFeRvFXgBaGUiA8?p=preview

    var app = angular.module('plunker', ['ui.multiselect']);
    
    app.controller('MainCtrl', function($scope) {
      $scope.roles = [{
        "roleGuid": "7b48aa01-7dad-4640-abcb-04d8e2666160",
        "roleName": "Electric",
        "workers": [{
          "WorkerName": "Bond, James",
          "WorkerGuid": "dac36324-2f7e-4dca-9e3a-2a9d8ac419ee"
        }, {
          "WorkerName": "Story, 843",
          "WorkerGuid": "85a234a9-3d86-41c2-832c-7a3d40977e88"
        }, {
          "WorkerName": "Test, SAT124",
          "WorkerGuid": "135149fb-b34e-4270-82f6-3488bd59a598"
        }, {
          "WorkerName": "Test, SAT-18_1",
          "WorkerGuid": "15bf6b49-5405-41a5-8473-cfe389bbb1ff"
        }, {
          "WorkerName": "Verma, Sunil",
          "WorkerGuid": "c785f1a1-34e3-4687-9df1-961331b62e0e"
        }, {
          "WorkerName": "Y, Venkata",
          "WorkerGuid": "ae18e61b-340e-4f27-92ac-c701026242c9"
        }, {
          "WorkerName": "Yadalla, Venkata",
          "WorkerGuid": "a9142270-e084-4c38-8e9f-448e647c8841"
        }]
      }, {
        "roleGuid": "e182d217-7806-4227-905e-ca64c7ac9b76",
        "roleName": "General Employee",
        "workers": [{
          "WorkerName": "1111, hen",
          "WorkerGuid": "93ef8fc9-6fcd-4d26-afca-7ba01968f9ab"
        }, {
          "WorkerName": "Giri, Ashok",
          "WorkerGuid": "2e0c7ba6-3a57-4970-a30c-68fba448492b"
        }]
      }, {
        "roleGuid": "270ad5e9-370a-43cc-927c-c9b275037447",
        "roleName": "Inspection Worker",
        "workers": [{
          "WorkerName": "Test, pals3",
          "WorkerGuid": "d447cd4a-9f19-463f-880b-9e09e830f9fd"
        }]
      }];
      $scope.selectedRoles = [];
    
      var selectableWorkers = (function() {
        return function(roles) {
          var selectableWorkers = [];
          if (!roles.length) {
            return selectableWorkers;
          }
          for (var i = 0, lenR = roles.length; i < lenR; i++) {
            for (var j = 0, lenW = roles[i].workers.length; j < lenW; j++) {
              selectableWorkers.push(roles[i].workers[j]);
            }
          }
          return selectableWorkers;
        };
      })();
    
      $scope.$watchCollection('selectedRoles', function(roles) {
        $scope.selectedWorkers = [];
        $scope.selectableWorkers = selectableWorkers(roles);
      });
    
      $scope.selectableWorkers = [];
      $scope.selectedWorkers = [];
    });