Search code examples
javascriptangularjsangular-ngmodelmultiple-select

Have a multiple ng-model workaround


I am displaying a list of users in a table, the last column of each row being a button. When the button is clicked a popup appears, that can edit the user related to the clicked row. Each user has a list of interests. In the popup, I have a multiple select in which I would like to display the user's current interests. When the popup appears for the first time, it fetches the right data, but when I try to click other rows several times, the data remains the same. I know this is because of the ng-model directive, so what workaround would be ideal for this situation?

Here is my multi-select

<select id="multipleSelect"
    data-placeholder="Select interests..."
    chosen
    multiple
    ng-model="$ctrl.activeInterests"
    ng-options="interest for interest in $ctrl.interests"
    style="width:370px; height:100px;">
    <option value=""></option>
</select>

When the button from the last column of the table is clicked this function is called

this.editButtonClicked = function(tableRowUser) {
    $scope.firstName = tableRowUser.firstName;
    $scope.lastName = tableRowUser.lastName;
    $scope.email = tableRowUser.email;
    $scope.role = tableRowUser.role;
    $scope.tag = tableRowUser.tag;
    $scope.username = tableRowUser.username;

    // Fetch the active interests
    fetchInterests($scope.tag);

    // Fetch the available interests the user can choose
    fetchAllAvailableInterests();

    // After this, make the Edit Form visible
    togglePopupClass();
}

And in the 'fetchInterests' function I make the data which is bonded to the ng-model empty again, without any success.

function fetchInterests(newInterests) {
    self.activeInterests = []; // <- Here I make it empty
    var interests = newInterests.split('|');

    for (i = 0; i < interests.length; i++) {
        // Trim the excess whitespace.
        var tag = interests[i].replace(/^\s*/, "").replace(/\s*$/, "");
        self.activeInterests.push(tag);
    }
}

The official documentation says that ng-model only re-renders if it assigned to an entirely new object or collection. I have tried this as well, but without any success.


Solution

  • Unfortunately, I can't tell you what's wrong with your solution based on the code you provided.

    Here's a quick demo which may help you solve your issue.

    // Code goes here
    angular.module('myApp', [])
    .controller('myCtrl', ['$scope', function($scope){
      
      $scope.allInterests = ['Cars', 'Football', 'Fishing', 'Pets', 'Cooking'];
      
      $scope.users = [
        {
          name: 'Bob',
          age: 34,
          interests: ['Cars', 'Football']
        },
        {
          name: 'Mary',
          age: 33,
          interests: ['Pets', 'Cooking']
        }
        ];
        
        $scope.showDetails = function(user){
          $scope.selectedUser = user;
        };
    }]);
    <!DOCTYPE html>
    <html>
    
      <head>
        <script data-require="[email protected]" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
        <link rel="stylesheet" href="style.css" />
        <script src="script.js"></script>
      </head>
    
      <body ng-app="myApp" ng-controller="myCtrl">
        
        <table>
          <tr ng-repeat="user in users">
            <td>{{user.name}}</td>
            <td>{{user.age}}</td>
            <td><button ng-click="showDetails(user)">Show interests</button></td>
          </tr>
        </table>
        
        <hr>
        
        Editing: {{selectedUser.name}} <br>
        Age: {{selectedUser.age}} <br>
        
        <select multiple ng-model="selectedUser.interests" ng-options="interest for interest in allInterests"></select> <br>
        
        Selected interests: {{selectedUser.interests.join(',')}}
        
      </body>
    
    </html>