Fork me on GitHub

logo
Blog / NanoJuice

a random developers blog



Default Select Option and AngularJS

I came into a slight headache when I was trying to autopopulate a select element's selected value, AngularJS handles things differently. Normally I iterate through the values in the template markup, then add an if statement to the option element to add the selected attribute.

Prefilling Selects The Old Way

This is how I would do it in Perl and TemplateToolkit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Example variables
my $stash = {
    object  => {
        id      => 1,
        category    => { id => 1, name => 'category 1' }
    },
    categories  => [
        { id => 1, name => 'category 1' },
        { id => 2, name => 'category 2' }
    ]
};
1
2
3
4
5
<select name="test">
[% FOREACH category IN categories %]
    <option[% IF object.category.id == category.id %] selected[% END %] value="[% category.id %]">[% category.name %]</option>
[% END %]
</select>

Prefilling Selects in AngularJS

The equivalent in AngularJS:

1
2
3
4
5
6
7
8
9
// Example variables
$scope.object = {
    id: 1,
    category: { id: 1, name: "category 1" }
};
$scope.categories = [
    { id: 1, name: "category 1" },
    { id: 2, name: "category 2" }
];
1
<select name="test" ng-model="object.category" ng-options="category.name for category in categories"></select>

The problem I ran into occurred because object.category is not a reference to something in the categories array. AngularJS will only set a default option if the ng-model value if a reference to an element in the ng-options array.

To solve this, I had to do some pre-processing in the controller, by iterating through the categories array, mapping the matching element to object.category

Mapping Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$scope.mapObjectToCategories = function() {
    if ($scope.object.category) {
        if ($scope.categories.length) {
            for (i = 0; i < $scope.categories.length; i++) {
                if ($scope.categories[i].id == $scope.object.category.id) {
                    console.log("Mapped " + $scope.object.category.id + " to categories index: " + i);
                    $scope.object.category = $scope.categories[i];
                }
            }
        }
    }
};

My next hurdle is converting this to a directive/service so that I dont have to replicate this code over and over.

Hope this helps someone else, as I couldnt find anything in my brief searching.

  • Dean