1
votes

I would like to set a default value for a select element:

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.js"></script>
  </head>
  <body ng-app="app">
    <div ng-controller="controller">
      <p>Year: {{ selectedYear }}</p>
      <p>Month: {{ selectedMonth }}</p>

      <select ng-model="selectedYear" ng-options="value for (key, value) in years track by value"></select>      
      <select ng-model="selectedMonth" ng-options="key as value for (key, value) in months track by key"></select>          
    </div>
  </body>
</html>

JavaScript:

angular.module("app", [])
.controller("controller", function($scope){
  $scope.months = ["Jan", "Fev", "Mar", "Abr"];
  $scope.selectedMonth = 0;

  $scope.years = [2015, 2016, 2017];
  $scope.selectedYear = 2015;
})

I've already tried this for month:

$scope.selectedMonth = 0;
$scope.selectedMonth = "Jan";
$scope.selectedMonth = $scope.months[0];

None seems to work. I've written it in codepen too: http://codepen.io/anon/pen/NGPPde?editors=101

Why my month is never selected by default?

3

3 Answers

1
votes

First, you cannot use select as and track by together. See here https://docs.angularjs.org/api/ng/directive/ngOptions

To address your issue, you need to understand that since you are using key as value for (key, value), this causes Angular to treat months as an object. This results in keys being strings, not integers. So make the following two changes:

Make this a string

$scope.selectedMonth = "0";

Remove track by

<select ng-model="selectedMonth" ng-options="key as value for (key, value) in months"></select>

Honestly though, for such a simple data model, it would be easier just to use <option ng-repeat> instead of ng-options.

1
votes

The documentation of ngOptions says:

Do not use select as and track by in the same expression. They are not designed to work together.

It also says that the notation for (key, value) is for object data sources, and not for array data sources.

So my guess is that the year preselection kind of works by accident, but that you shouldn't rely on it. Instead, stick to the documented usage. Simply transform you array of month names into an array of objects:

$scope.monthObjects = $scope.months.map(function(monthName, index) {
    return {
        index: index,
        name: monthName
    };
});

and use

ng-options="month.index as month.name for month in monthObjects"

and

$scope.selectedMonth = 0;
0
votes

Just needed to update the ng-options directive to

month for month in months

That's of course if you want to keep the selectedMonth variable as a string value of what is shown and not a number value like 0.

Hope that helps you out!