http://stackoverflow.com/questions/42413421/knockout-bound-select-dropdown-with-default-text-and-two-way-value-binding

by jlspake

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<div>
  <select id="periodSelect" class="form-control" data-bind="value: selectedOption, event: { change: onChange }">
    <option>-No Selection-</option>
    <!--ko foreach: {data: customGroups}-->
    <optgroup data-bind="attr: { label: label}">
        <!--ko foreach: {data: customPeriods}-->
        <option data-bind="text: $data.label, value: $data"></option>
        <!-- /ko -->
    </optgroup>
    <!-- /ko -->
</select>
</div>

JavaScript

var data = [
  	{
      "label": 2016,
      "customPeriods": [{
          "customFrequencyId": 1008,
          "startDate": "2016-10-29T00:00:00Z",
          "endDate": "2016-11-25T00:00:00Z",
          "label": "P11 2016"
      }, {
          "customFrequencyId": 1008,
          "startDate": "2016-11-26T00:00:00Z",
          "endDate": "2016-12-31T00:00:00Z",
          "label": "P12 2016"
      }]
    }, 
    {
        "label": 2017,
        "customPeriods": [{
            "customFrequencyId": 1008,
            "startDate": "2017-01-01T00:00:00Z",
            "endDate": "2017-01-28T00:00:00Z",
            "label": "P1 2017"
        }, {
            "customFrequencyId": 1008,
            "startDate": "2017-01-29T00:00:00Z",
            "endDate": "2017-02-25T00:00:00Z",
            "label": "P2 2017"
        }, {
            "customFrequencyId": 1008,
            "startDate": "2017-02-26T00:00:00Z",
            "endDate": "2017-03-23T00:00:00Z",
            "label": "P3 2017"
        }]
    }
  ];

var viewModel = function(callback){
		var base = this;

    //Verco.Services.GetData("GetPeriods", { frequency: customFrequency },
    setTimeout(function () {
      result = data; //simulated callback using data variable
      if (result.length > 0) {
        _.each(result, function (period) {
          base.customGroups.push(period);
        });
        base.setValueByLabel("P2 2017");
      }
    }, 1000);
  
  	this.callback = callback;
  	this.customFrequency = 0;
    this.customGroups = ko.observableArray([]);
    this.selectedOption = ko.observable();
    this.selectedOption.subscribe(function(newValue){
    	console.log(newValue);
    });

    this.onChange = function() {
        if (base.callback !== null) {
            base.callback(base.selectedOption());
        }
    };
    
    this.setValueByLabel = function(label){
    	for(var i=0; i<base.customGroups().length; i++){
      		var group = base.customGroups()[i];
      		for(var j=0;...