KnockoutJS - Binding value of select with optgroup and javascript objects

http://stackoverflow.com/questions/11189660/knockoutjs-binding-value-of-select-with-optgroup-and-javascript-objects

by Jorgelig

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="https://rawgithub.com/ivaynberg/select2/master/select2.js"></script>
<link rel="stylesheet" href="http://ivaynberg.github.com/select2/select2-master/select2.css">
<select data-bind="foreach: groups, value: selectedOption">
    <optgroup data-bind="attr: {label: label, 'data-label': label}, foreach: children">
        <option data-bind="text: label, option: $data"></option>
    </optgroup>
</select>

        
<hr />

<div data-bind="text: specialProperty"></div>

CSS

.select2-results img { height: 25px; width: 25px }
.select2-container { width: 200px; }

JavaScript

ko.bindingHandlers.option = {
    update: function(element, valueAccessor) {
       var value = ko.utils.unwrapObservable(valueAccessor());
       ko.selectExtensions.writeValue(element, value);   
    }        
};

function Group(label, children) {
    this.label = ko.observable(label);
    this.children = ko.observableArray(children);
}

function Option(label, property) {
    this.label = ko.observable(label);
    this.someOtherProperty = ko.observable(property);
}

var ViewModel = function() {
    this.groups = ko.observableArray([
        new Group("Group 1", [
            new Option("Option 1", "A"),
            new Option("Option 2", "B"),
            new Option("Option 3", "C")
        ]),
        new Group("Group 2", [
            new Option("Option 4", "D"),
            new Option("Option 5", "E"),
            new Option("Option 6", "F")
        ])
    ]);

    this.selectedOption = ko.observable();

    this.specialProperty = ko.computed(function(){
        var selected = this.selectedOption();
        return selected ? selected.someOtherProperty() : 'unknown';
    }, this);
};

ko.applyBindings(new ViewModel());

function format(state) {
    console.log(state);
    if (state.element[0].nodeName === "OPTGROUP") {
       return "<img src='https://www.google.com/images/srpr/logo4w.png' />" + state.text; 
    }
    
    return state.text;
}

$("select").select2( {
    allowClear: true,
    placeholder: 'testing',    
    //formatResult: format,
    escapeMarkup: function(m) { return m; }
});