Sweetalert2: [Bug] InputOptions for Select and Radio have an implicitly defined object sort

Created on 11 Jan 2018  ·  10Comments  ·  Source: sweetalert2/sweetalert2

So I have a list of things coming back from a database. Lets say they have an id and a name. The id is from the database.
{ id: 4, name: "nick" }
{ id: 10, name: "dave" }
{ id: 2, name: "zac" }

I'm setting the inputOptions parameter but it seems to only accept a string array. I use the id as the index and the value is the name. But now the select will order my list by the database id. Is there a way to separate the id from the ordering? The ideal would be setting inputOptions to an array of objcts with an id and value. It could then order by the array and retain the id for the select value.

Hope that made sense?

bug feature

Most helpful comment

@nickraphael Maps support has been added :tada:

Here's the jsfiddle with your data: https://jsfiddle.net/ad3quksn/348/

const items = [ 
  { id: 4, name: "nick" },
  { id: 10, name: "dave" },
  { id: 2, name: "zac" },
]

const inputOptions = new Map
items.forEach(item => inputOptions.set(item.id, item.name))

swal({
  input: 'select',
  inputOptions,
  inputValue: 10
})

All 10 comments

"If input parameter is set to 'select' or 'radio', you can provide options. Object keys will represent options values, object values will represent options text values."

So do something like this:

inputOptions: {
  4: "nick",
  10: "dave",
  2: "zac"
}

(See https://jsfiddle.net/ad3quksn/320/)

You fiddler orders the select as Zac, Nick Dave. I assume because thats the number order (2,4,10). But I want it in the order I created the inputOptions (nick, dave, zac).

@nickraphael I apologize, misunderstood the issue. As I explore it more, it looks like this will actually need a PR to fix. Thanks for the report!

It looks like the JS engine will automatically sort object keys. Example

Code in source sweetalert2.js#L1121-L1133

My suggestion would be to have a specific object structure and to accept an array of object instead:

inputOptions: [
  {id: 4, value: 'option1'},
  {id: 6, value: 'option2'},
  {id: 5, value: 'option3'}
]

Changing name of issue for clarity.

Let's not fix the issue of JS engine in this tiny UI plugin :)

My suggestion is to add some spaces to inputOptions keys before passing it to swal(): https://jsfiddle.net/ad3quksn/324/

SweetAlert2 will autotrim the result value for you, so you will get the expected value and select will keep the order of items.

From Node.js REPL:

> {3: 3, 2: 2, 1: 1}
{ '1': 1, '2': 2, '3': 3 }

Interesting JS quirk I did not know about!

@limonte We can't fix this issue with JS, but we could work around it by accepting alternate formats: array of objects ({ id, text }) or array of strings (for when the id and the text are the same).

The other advantage of this is that arrays are easier to manipulate than objects.

This shouldn't be hard to accomplish, or add much complexity. I can submit a PR if this sounds acceptable @limonte. (I know I have a lot of pending PRs, but they're coming!)

This shouldn't be hard to accomplish, or add much complexity. I can submit a PR if this sounds acceptable @limonte.

I think you underestimating the complexity of this change. How to match which key will represent the key, which will represent the value? What will happen with key duplicates? What if some key isn't present - null or undefined?

This is out of scope of SweetAlert2. I hope our users are able to write a one-liner to provide the data in the expected format, e.g. the array from this issue can be easily converted to object:

https://jsfiddle.net/ad3quksn/325/

I quite agree.
(By the way, the keys order in the objects is in fact unspecified and are left to the implementation).

However... we could eventually support Map which is an adapted data structure for that type of use cases.

inputOptions: new Map([
    [1 , "Linus Torvalds"],
    [2, "Richard Stallman"]
]),

Map is an iterable, is standard, preserves insertion order, and is already documented. It also probably requires less lines of code for us (than a custom array+objects structure) and has a compact declaration syntax.

However... we could eventually support Map which is an adapted data structure for that type of use cases.

Maps are cool because they will take care of key dups out of the box:

Maps are supported by IE11 and easy to add, I'll do that!

What will happen with key duplicates? What if some key isn't present - null or undefined?

I would have said "It shouldn't really matter, whether the duplicates are removed or an error is thrown, or neither. Garbage in, garbage out." I didn't understand the first (not quoted) question/concern.

But I agree using Map is much better.

@nickraphael Maps support has been added :tada:

Here's the jsfiddle with your data: https://jsfiddle.net/ad3quksn/348/

const items = [ 
  { id: 4, name: "nick" },
  { id: 10, name: "dave" },
  { id: 2, name: "zac" },
]

const inputOptions = new Map
items.forEach(item => inputOptions.set(item.id, item.name))

swal({
  input: 'select',
  inputOptions,
  inputValue: 10
})
Was this page helpful?
0 / 5 - 0 ratings

Related issues

samturrell picture samturrell  ·  3Comments

gouhary picture gouhary  ·  3Comments

smachs picture smachs  ·  3Comments

Hydro8 picture Hydro8  ·  3Comments

mayvn10 picture mayvn10  ·  4Comments