3

I want to create a dropdown from enum data type but when I try to change enum into object with name and value; enum array return twice of the enum member. using a function from this SO post

  • Typescript: v 2.3.3

  • Angular v 4.3.4

ps. can not update typescript version dues to angular version. below is the relevant code

export enum FrequencyEnum {
    H1 = <any>'1 Hour',
    H12 = <any>'12 Hours',
    D1 = <any>'24 Hours',
    D7 = <any>'7 Days',
    M1 = <any>'1 Month',
    M3 = <any>'3 Months',
    CD = <any>'Custom Date Range'
};
export interface Frequency {
    name: string;
    value: string;
    range?: { from: string; to: string; };
}

export function enumSelector(definition) {
    console.log('definition: ', definition);
    return Object.keys(definition)
        .map(key => ({ value: definition[key], name: key }));
}

this.frequnecyList = enumSelector(FrequencyEnum);

it gives array of 14 objects

[
  {
    "value": "1 Hour",
    "name": "H1"
  },
  {
    "value": "H1",
    "name": "1 Hour"
  },
  {
    "value": "12 Hours",
    "name": "H12"
  },
  {
    "value": "H12",
    "name": "12 Hours"
  },
  {
    "value": "24 Hours",
    "name": "D1"
  },
  {
    "value": "D1",
    "name": "24 Hours"
  },
  {
    "value": "7 Days",
    "name": "D7"
  },
  {
    "value": "D7",
    "name": "7 Days"
  },
  {
    "value": "1 Month",
    "name": "M1"
  },
  {
    "value": "M1",
    "name": "1 Month"
  },
  {
    "value": "3 Months",
    "name": "M3"
  },
  {
    "value": "M3",
    "name": "3 Months"
  },
  {
    "value": "Custom Date Range",
    "name": "CD"
  },
  {
    "value": "CD",
    "name": "Custom Date Range"
  }
]

how can I get only 7 value ( equal to enum member) in the final array?

1 Answer 1

3

I'm afraid it's not really possible due to the way TypeScript implements enums. If you look at the generated JavaScript code for your enum, you'll see:

var FrequencyEnum;
(function (FrequencyEnum) {
    FrequencyEnum[FrequencyEnum["H1"] = '1 Hour'] = "H1";
    FrequencyEnum[FrequencyEnum["H12"] = '12 Hours'] = "H12";
    FrequencyEnum[FrequencyEnum["D1"] = '24 Hours'] = "D1";
    FrequencyEnum[FrequencyEnum["D7"] = '7 Days'] = "D7";
    FrequencyEnum[FrequencyEnum["M1"] = '1 Month'] = "M1";
    FrequencyEnum[FrequencyEnum["M3"] = '3 Months'] = "M3";
    FrequencyEnum[FrequencyEnum["CD"] = 'Custom Date Range'] = "CD";
})(FrequencyEnum || (FrequencyEnum = {}));
;

An assignment expression in JavaScript returns its right value, meaning that FrequencyEnum["H1"] = '1 Hour' evaluates to 1 Hour and effectively gives you a property '1 Hour' with value "H1" in the resulting object. That's why you see the the values also appearing as the keys and hence twice the size of key/values that you expect.

You can do a trick and filter out every even key in the list, but it's not a very solid solution:

export function enumSelector(definition: any) {
    return Object.keys(FrequencyEnum)
                 .filter((key, i) => i % 2 == 0)
                 .map(key => ({ value: definition[key], name: key }))
}

This will give you the output:

[ { value: '1 Hour', name: 'H1' },
  { value: '12 Hours', name: 'H12' },
  { value: '24 Hours', name: 'D1' },
  { value: '7 Days', name: 'D7' },
  { value: '1 Month', name: 'M1' },
  { value: '3 Months', name: 'M3' },
  { value: 'Custom Date Range', name: 'CD' } ]

Another (better) solution is to not use enums and simply use an object literal instead of an enum:

const FrequencyEnum = {
    H1: '1 Hour',
    H12: '12 Hours',
    D1: '24 Hours',
    D7: '7 Days',
    M1: '1 Month',
    M3: '3 Months',
    CD: 'Custom Date Range'
};
Sign up to request clarification or add additional context in comments.

3 Comments

Yes I did the same constant approach. thanks for the solution.
You mean using the object literal instead of the enum? Also please accept the answer if you're happy with it :-)
yes object literal instead of enum. there was one more way to use npm package enum-string but that was lengthy way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.