20

So, What I'm trying to do is fairly simple with vanilla JS, but I'm using AngularJS and I would like to know how to do it the best way within the framework. I want to update the selected options in a multiple select box. I do not want to add or remove any of the options. Here is what my HTML looks like:

<select multiple>
    <option value="1">Blue</option>
    <option value="2">Green</option>
    <option value="3">Yellow</option>
    <option value="4">Red</option>
</select>

Using the following array, I'd like to programmatically select/deselect options from this list:

[{id:1, name:"Blue"},{id:4, name:"Red"}]

When I set this array in the scope, I want the select box to deselect anything that is not Blue or Red and select Blue and Red. The standard response that I've seen on the Google Groups is to use ng-repeat. However, I can't recreate the list every time because the list of selected values is incomplete. As far as I can tell, AngularJS has no mechanism for this, and I'm at a loss as to how I would do this without resorting to using jQuery.

monitorjbl
  • 4,280
  • 3
  • 36
  • 45
  • I feel pretty confident I could solve this if you make me a jsbin.com or similar site example that I can look at and leave some notes on what is wrong / what you expect, etc. I find angular makes a lot of things pretty easy. :) – m59 Sep 12 '13 at 06:23

1 Answers1

29

ngModel is pretty awesome! If you specify the indexes as a model selectedValues

<select multiple ng-model="selectedValues">

built from your list (selected) in a $watch

$scope.$watch('selected', function(nowSelected){
    // reset to nothing, could use `splice` to preserve non-angular references
    $scope.selectedValues = [];

    if( ! nowSelected ){
        // sometimes selected is null or undefined
        return;
    }

    // here's the magic
    angular.forEach(nowSelected, function(val){
        $scope.selectedValues.push( val.id.toString() );
    });
});

ngModel will automatically select them for you.

Note that this data binding is one-way (selected to UI). If you're wanting to use the <select> UI to build your list, I'd suggest refactoring the data (or using another $watch but those can be expensive).

Yes, selectedValues needs to contain strings, not numbers. (At least it did for me :)

Full example at http://jsfiddle.net/JB3Un/

PixnBits
  • 1,150
  • 10
  • 14
  • Thanks for the answer! I do unfortunately need this to be two-way, it's for an edit-style page. Is there a way you would refactor this to make it work in a multiple select box? My problem is mainly that I'm not how to approach this with Angular. – monitorjbl Sep 11 '13 at 21:47
  • 1
    If all you're looking for is ['red','blue'] then use those as the values of your ` – PixnBits Sep 13 '13 at 20:17
  • I think this came down to a lack of understanding about Angular on my part. Because I was more or less decoupling the model I was using from the view, I needed to have an intermediary variable to handle transferring between the two. I load the list of values with AJAX, so I just added some code to put the values into selectValues instead of using $watch. Your answer helped me a lot in figuring that out, thank you so much! – monitorjbl Sep 19 '13 at 00:40
  • 1
    The magic is in the `.push()`. Changing the array with assignment does NOT work. – boatcoder Apr 08 '14 at 05:51
  • @PixnBits Steller answer! – Val May 09 '17 at 02:28