#469·enquirer

Using `this.map` in `result()` of Autocomplete maps filtered-out choices to `undefined`

Author: DivvyByZeroCreated Aug 8, 2024Updated Aug 8, 2024

Given the following code:

javascript
const result = await prompt({
  type: "autocomplete",
  multiple: true,
  limit: 10,
  name: "selection",
  message: "Please select items",
  choices: Array(100).fill().map((_, index) => ({
    name: `Option ${index + 1}`,
    value: index
  })),
  result (selected) {
    return this.map(selected);
  }
});

console.dir(result);

If the user, for example, selects "Option 1" and then types "Option 4" to filter (autocomplete behavior) and select "Option 42", and then presses Enter, the output will be:

javascript
{ selection: { "Option 1": undefined, "Option 42": 41 } }

With expected output:

javascript
{ selection: { "Option 1": 0, "Option 42": 41 } }

Enquirer Version: 2.4.1 Operating System: Windows 11 Error Messages: None Extensions, Plugins, Helpers, Etc.: None

Observations / Investigations: If the user clears the "Option 4" they typed (i.e., backspace it away) before pressing Enter, "Option 1" will be mapped correctly. From a brief look at the code, I saw that this.map calls this.find under-the-hood, and this.find references this.choices for assigning its values, however in the Autocomplete prompt, this.choices is modified via the closed suggest function. Therefore when the user leaves input in the autocomplete buffer and submits, the this.find method will only map suggested values which currently populate this.choices.

Workaround: In the result() method, set this.choices to this.state._choices before calling this.map, like so:

javascript
result (selected) {
  this.choices = this.state._choices;
  return this.map(selected);
}

Final Thoughts: As I am uncertain how else the this.find method is used, I am hesitant to suggest that its logic should be update to use this.state._choices as opposed to this.choices, but that might be the solution, depending.