2

Simple problem, probably discussed many times, but I can't find a proper solution on this simple issue.

The problem:
modifications on selected items have no effect on the view (which it should).

Controller:

var myApp = angular.module('myApp', ['ui.select2']);

function MyCtrl($scope) {
    $scope.selectedDaltons = [4]; // Averell is preselected (id:4)
    $scope.daltons = [
        { id: 1, name: 'Joe' },
        { id: 2, name: 'William' },
        { id: 3, name: 'Jack' },
        { id: 4, name: 'Averell' },
        { id: 5, name: 'Ma' }
    ];
    $scope.changeAverellsName = function() {
        // Fiddle's issue!! 
        // observe, that the selected item on the view does not change!!
        $scope.daltons[3].name = "Idiot";
    };
};

View:

<div ng-controller="MyCtrl">

    <!-- changing model via click -->
    <button ng-click="changeAverellsName()">change Averell's name to 'Idiot'</button>

    <!-- selected items are not binded to the model -->
    <select multiple ui-select2 class="form-control" id="70.1.6.3" data-ng-model="selectedDaltons">
        <option data-ng-repeat="dalton in daltons" value="{{dalton.id}}" text="">{{dalton.name}}</option>
    </select>

    <!-- this list is for assure, that two way binding works -->
    <ul>
        <li data-ng-repeat="dalton in daltons">{{dalton.name}}</li>
    </ul>
</div>


Here as jsfiddle


How can I make the two way binding work?

1 Answer 1

3

From the source code here on line 134 where the source collection is being watched, it's only watching for the collection to change (items removed or added) and not the values of the item properties to change. To watch item property changes as well, the watch would need to be coded as:

scope.$watch(watch, function (newVal, oldVal, scope) { 
  if (angular.equals(newVal, oldVal)) { 
    return; 
  } 
  // Delayed so that the options have time to be rendered 
  $timeout(function () { 
    elm.select2('val', controller.$viewValue); 
    // Refresh angular to remove the superfluous option 
    controller.$render(); 
    if(newVal && !oldVal && controller.$setPristine) { 
      controller.$setPristine(true); 
    } 
  }); 
}, true); 

Notice the 'true' at the end of the watch function. To get around that, you would need to use map to copy your source collection back into itself.

Sign up to request clarification or add additional context in comments.

1 Comment

thank you very much... I made another fiddle to proof it! the select2 refers to an edited version of select2.js

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.