2
\$\begingroup\$

I need to bind a dropdown to an enum. For this I've made a key_value_pair class and I manually go through each enum option to add it. Is there a more elegant way to achieve this?

HTML:

<select data-bind="options: regions, value: region, optionsValue: 'key', optionsText: 'value'"></select>

TypeScript:

class key_value_pair<key_type, value_type>
{
    key: key_type;

    value: value_type;

    constructor(key: key_type, value: value_type)
    {
        this.key = key;

        this.value = value;
    }
}

class calculator
{
    regions: KnockoutObservableArray<key_value_pair<number, string>>;

    region: KnockoutObservable<API.region>;

    constructor()
    {
        this.regions = ko.observableArray();
        this.regions.push(new key_value_pair(API.region.US, API.region[API.region.US]));
        this.regions.push(new key_value_pair(API.region.Europe, API.region[API.region.Europe]));
        this.regions.push(new key_value_pair(API.region.Korea, API.region[API.region.Korea]));
        this.regions.push(new key_value_pair(API.region.Taiwan, API.region[API.region.Taiwan]));
        this.regions.push(new key_value_pair(API.region.China, API.region[API.region.China]));

        this.region = ko.observable();
    }
}
\$\endgroup\$
1
\$\begingroup\$

Your solution works fine and I didn't find a better solution. I've just upgraded it little bit, by automatic fill the options, so it is usable to any Enum class.

Here I found how to enumerate Enum type

export class SelectEditorObject
{
    private options: KnockoutObservableArray<keyValuePair<number, string>>;
    private selection: KnockoutObservable<number>;

    constructor(e: any, value: number)
    {
        var options = SelectEditorObject.getNamesAndValues(e);
        this.selection = ko.observable<number>(value);
        this.options = ko.observableArray<keyValuePair<number, string>>(options);
    }

    public toString()
    {
        var selected = undefined;
        this.options().forEach((pair) =>
        {
            if (pair.key === this.selection())
            {
                selected = pair.value;
            }
        }, this);
        return selected;
    }

    public getValue()
    {
        return this.selection();
    }

    private static getNames(e: any)
    {
        return Object.keys(e).filter(v => isNaN(parseInt(v, 10)));
    }

    private static getValues(e: any)
    {
        return Object.keys(e).map(v => parseInt(v, 10)).filter(v => !isNaN(v));
    }

    public static getNamesAndValues(e: any): Array<keyValuePair<number, string>>
    {
        return SelectEditorObject.getValues(e).map(v => { return new keyValuePair(v, e[v]) });
    }
}

export class keyValuePair<key_type, value_type>
{
    public key: key_type;
    public value: value_type;
    constructor(key: key_type, value: value_type)
    {
        this.key = key;
        this.value = value;
    }
}
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! Your answer proposes an alternative solution without reviewing the code. Please read the following meta to see what makes for good answers and what doesn't. \$\endgroup\$ – Mast Oct 8 '15 at 12:48
  • \$\begingroup\$ Sorry, I am new here and i don't understand what is wrong woth my post. I don't propose alternative solution, just improving reuseability of this class. What is, in fact, answer to original post, where author asks, if there was the better solution than go through each value. \$\endgroup\$ – prespic Oct 8 '15 at 15:34
  • \$\begingroup\$ I should've stated that better. You answered with a re-write without stating why yours is better. Code Review is all about explaining why something is better, so a little explanation of why you made these changes would turn it into a decent answer. \$\endgroup\$ – Mast Oct 8 '15 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.