7

I have a javascript function to populate dropdowns for individual table rows like:

$scope.possibleOptions = getUniqueValues($scope.yypeOptions, 'yypeOption')
    .map(function(id) {
            return {
                id: id,
                name: id
            });

function getUniqueValues(array, prop) {
    return [...new Set(array.map(item => item[prop]))];
}

where, $scope.yypeOptions is:

$scope.yypeOptions = [{
    yypeOption: "option1"
}, {
    yypeOption: "option2"
}];

I now have to make it compatible to IE. The spread and => operator is something I have to replace.

Went through this and this link. But I could not get any understanding how to replace the Set inside an Array feature.

Mike
  • 721
  • 1
  • 17
  • 44
  • Maybe you should take a look at [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill)... – JO3-W3B-D3V Feb 11 '19 at 16:44
  • 3
    Are you sure that your IE version supports `...` (spread) operator? – Kosh Feb 11 '19 at 16:45
  • 1
    @KoshVery I was just about to edit my comment regarding this syntax, not to mention the support for [`Set`](https://caniuse.com/#search=set)... – JO3-W3B-D3V Feb 11 '19 at 16:45
  • $injector is an Angular thing, right? Does this need an Angular tag? – Wyck Feb 11 '19 at 16:46
  • 2
    And `Set`--we can't just say "IE", we need to specify the version (and whether you actually mean IE or Edge, because some people think Edge is IE). – Dave Newton Feb 11 '19 at 16:46
  • [IE11 does not support spread.](http://kangax.github.io/compat-table/es6/#test-spread_(...)_operator) Go through your code and ensure that the features you are using are supported by the browser you are targeting. Use a linter to expedite the process. – zero298 Feb 11 '19 at 16:51
  • ....or just use a browser – messerbill Feb 11 '19 at 16:52
  • Thank you for your response guys :) I use IE 11 – Mike Feb 11 '19 at 16:53

5 Answers5

9

Here is a simple way that could work on IE

data =[{name:"a"}, {name:"a"},{name:"x"}]

function getUniqueValues(array, prop) {
    return array.map(function(item) { return item[prop]; })
    .filter(function (item, index, self){ return self.indexOf(item) === index; }); // distinct
}

console.log(getUniqueValues(data, "name"))
Alen.Toma
  • 4,684
  • 2
  • 14
  • 31
3

The getUniqueValues there is performing two things for you; removing duplicated elements and also cloning the array. However, the map already is a clone of the array, so you just need to remove duplicates; you could use something like this:

function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

function getUniqueValues(array, prop) {
    function mapper(item) {
        return item[prop];
    }
    return array.map(mapper).filter(onlyUnique);
}

I'd suggest you to take a look at stuff like webpack and babel in order to use the latest JS and also work on IE, by using transpiler and polyfills to generate compatible code ;)

PS. I don't have IE right now to test if filter works, but I'm pretty sure it does; otherwise you could remove duplicates by hand with a plain old for.

Luan Nico
  • 5,376
  • 2
  • 30
  • 60
3

Your two syntaxes that you are asking about are the fat arrow for arrow functions and the spread operator. You can replace the former with a standard function expression and the latter with iteration using forEach that adds the elements to an array. In addition, you also need a replacement for the Set constructor that initializes it from an iterable. Instead, you need to add the elements one by one.

You can write your function like this. This first adds all values into a set, and then gets the values from the list and back to a new array:

function getUniqueValues(array, prop) {
    // create set
    var set = new Set();
    array.forEach(function (item) {
        set.add(item[prop]);
    });

    // convert set to array
    var result = [];
    set.forEach(function (item) {
        result.push(item);
    });
    return result;
}

Since there is basic support for Set, including forEach, in Internet Explorer 11, you can use this without a polyfill.

Here is an example that runs fine in Internet Explorer 11:

var options = [
    { yypeOption: "option1" },
    { yypeOption: "option2" },
    { yypeOption: "option1" },
    { yypeOption: "option1" },
    { yypeOption: "option3" },
];

function getUniqueValues(array, prop) {
    var set = new Set();
    array.forEach(function (item) {
        set.add(item[prop]);
    });
    var result = [];
    set.forEach(function (item) {
        result.push(item);
    });
    return result;
}

console.log(getUniqueValues(options, 'yypeOption'));
poke
  • 369,085
  • 72
  • 557
  • 602
  • Hi Poke. The IE throws `TypeError: Unable to get property 'map' of undefined or null reference` – Mike Feb 17 '19 at 11:16
  • Hi Poke. Thanks a lot. But I have to go with @Alen, considering 1. Simplest solution code. 2.Testing and answering without edits. – Mike Feb 17 '19 at 11:27
  • This seems to be fair. Sure Poke :) – Mike Feb 17 '19 at 11:36
2

If you are targeting IE11, since it does not support ES6 features like "=>", you have 2 options:

1) include a polyfill like babeljs so that the ES6 code works in IE11

  • I have not done this previously but I read that this is what polyfills do

OR

2) replace your ES6 code with equivalent ES5 code

user637563
  • 346
  • 3
  • 15
1

I think The problem is not related with 'map',
actually you should not use spread operator (...) in IE11. you may check it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

emrah
  • 71
  • 1
  • 3
  • Hi Emrah, yes got it. Even the => seems to be not supported in IE11. Any help on how can I resolve this? – Mike Feb 17 '19 at 08:49