Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user-created choices for selects #525

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

kittee
Copy link

@kittee kittee commented Feb 21, 2019

Description

  • Added a new configuration option called addChoices which affects selects. It is false by default to maintain old behavior.
  • When addChoices is set to true, the user can type an option into the field and press enter, and it will be added as a new option and selected.

Motivation and Context

This addresses #39 which is allowing users to add choices to selects.

How Has This Been Tested?

It works on the project I'm working on. The existing tests and new tests that I added pass.

Screenshots (if appropriate):

add-choices-demo

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

@kittee
Copy link
Author

kittee commented Mar 15, 2019

I have rebased with master to fix merge conflicts since I opened this PR, added tests, added a gif demo, and updated the readme. Please let me know if there's anything else I can address so this can be considered for merging. ✧・゚:*╰(◕‿◕。╰)

@AdamWills
Copy link

Is there any chance that this feature could be added?

@jshjohnson
Copy link
Collaborator

Sorry, I've been really busy recently. Will get this reviewed and merged ASAP

@jayraydon
Copy link

Hi, just wondering if/when this will be reviewed and merged? Very keen on using this feature :)

@mlshvdv
Copy link

mlshvdv commented Jul 8, 2019

@caramiki @jshjohnson guys any news about this amazing feature? thanks

@AdamWills
Copy link

Is there anything we can do to help with getting this feature added?

@GoldenMaximo
Copy link

GoldenMaximo commented Jul 26, 2019

Please add this. I had to develop it on my own.

userchoice

Ended up with a makeshift workaround code.

const choicesIssue39Fix = (choicesElement) => {
    choicesElement.input.element.addEventListener('keydown', (keypressEvent) => {
        if (keypressEvent.keyCode === 13 && keypressEvent.target.value) {
            let keywordHits = 0;
            [...choicesElement.choiceList.element.children].forEach((element) => {
                if (element.innerText.includes(keypressEvent.target.value)) {
                    keywordHits += 1;
                }
            });
            if (!keywordHits) {
                keypressEvent.stopPropagation();
                choicesElement.setChoices([
                    {
                        value: keypressEvent.target.value,
                        label: keypressEvent.target.value,
                        selected: true,
                    },
                ], 'value', 'label', false);
                const linterEvent = keypressEvent;
                linterEvent.target.value = '';
            }
        }
    });
};

Edit: I've just now realized I forgot to change the "No results found" caption to "Press enter to add" like the OP

@BlaM
Copy link

BlaM commented Aug 30, 2019

As far as I can tell pressing enter always adds the content of the search field as new item, even when I try to select another element in the list via cursor keys.

That's kind of counterintuitive to me.

press-enter

@GoldenMaximo
Copy link

As far as I can tell pressing enter always adds the content of the search field as new item, even when I try to select another element in the list via cursor keys.

That's kind of counterintuitive to me.

press-enter

I don't know if this issue has been fixed already or if you were using the code I've made but my fix is pretty modifiable and it's working fine in production, I'm pretty sure you can come up with a reasonable solution based on it.

@BlaM
Copy link

BlaM commented Aug 30, 2019

I don't know if this issue has been fixed already or if you were using the code I've made but my fix is pretty modifiable and it's working fine in production, I'm pretty sure you can come up with a reasonable solution based on it.

I tried to use the pull request implementation, not yours. That'll be the next step for me ;)

... Few moments later:

@GoldenMaximo: Your implementation feels more like what I would expect.

@jshjohnson jshjohnson added the feature Pull request that adds new functionality label Oct 30, 2019
@jshjohnson
Copy link
Collaborator

As far as I can tell pressing enter always adds the content of the search field as new item, even when I try to select another element in the list via cursor keys.

That's kind of counterintuitive to me.

I agree this is counterintuitive - a solution to add choices dynamically needs to be able to differentiate between selecting an existing choice and adding a non-existent choice

@vitobotta
Copy link

Hi! Is there any update about this feature? Thanks

@vitobotta
Copy link

Hi @GoldenMaximo , I am trying your workaround but I get Cannot read property 'element' of undefined. I have tried with both the Choices object and the select element on which I initialise Choices. Can you clarify how to use the workaround? Thanks!

@BlaM
Copy link

BlaM commented Feb 17, 2020

You may have to use an older Version of this library to use the exact code example. I can confirm, that it worked for me, but back then choices.js was at version 7.x.x 6 months ago, now it is at 9.x.x.

@vitobotta
Copy link

Thanks @BlaM . I ended up using Tagify for tags.

@devkral
Copy link

devkral commented Apr 15, 2020

why is a new option introduced?
Why not just checking if the type is a multiple-select and addItems is set?

Edit: I misunderstood the addItems flag

@devkral
Copy link

devkral commented Apr 16, 2020

I reworked this PR and made an other PR:
#856

There are many edge cases which need to be handled (like disabled options).

@maxp-hover
Copy link

I'm confused, isn't this in the demo? Look at the first example here https://joshuajohnson.co.uk/Choices/

Is or isn't this actually supported?

@maxp-hover
Copy link

Ok sorry, I understand now. Adding new elements only works for input types, not select. That wasn't very well documented.

@joe-nghiem-goldenowl
Copy link

Excuse me, when is this feature implemented ? I want to use this feature in my project. Can you implement this feature soon, please ? Thanks.

@helenatxu
Copy link

Please, I'm waiting for this feature too. I would like to keep using this awesome select box, but I need to add the user input when it's a select.

@rizkhal
Copy link

rizkhal commented Dec 27, 2021

I think we need this feature for single select too, not just on tags select

@kabirpathak
Copy link

Like @rizkhal, I really need this feature in single select. Any news on when and if this will be merged? How can i help in speeding up this MR?

@joeworkman
Copy link

Sadly, this PR would need to be completely redone. This library has been completely revamped into TS. Merging this PR isn't possible without redoing most of it.

@joeworkman
Copy link

I re-implemented this PR under the new code base. #1117

@SieSiongWong
Copy link

@GoldenMaximo I like the workaround you've come out with. Will it be possible that you can share the full example as I'm newbie to javascript and not sure where should I include the "const choicesIssue39Fix" you've developed. Much Appreciated!

@vstruk01
Copy link

vstruk01 commented Aug 28, 2023

Waiting for this feature, are there any updates ?

@Purek
Copy link

Purek commented Dec 8, 2023

I re-implemented this PR under the new code base. #1117

Thank you for your perfect implementation, and I hope the author can merge as soon as possible.

@open-admin-org
Copy link

Made my own implementation (read: hack)

  function choicesjs_allow_create(obj) {
  
      var addNew = document.createElement("div");
      var choiceList = obj.choiceList.element;
      addNew.addEventListener('click', function (e) {
          addItem();
      })
  
      obj.input.element.addEventListener('keyup', function (e) {
  
          if (addNewAllowed()) {
              obj.removeHighlightedItems();
              obj._currentState.choices.map(elm => elm.active = false)
              addNew.innerHTML = "Press ENTER to add: <b>" + obj._currentValue + "</b>";
              addNew.className = "choices__item choices__item--choice";
              addNew.style.display = "block";
              addNew.dataset.choiceSelectable = '';
              choiceList.append(addNew)
  
              var code = (e.keyCode ? e.keyCode : e.which);
              if (code == 13) {
                  e.preventDefault()
                  e.stopPropagation()
                  return false;
              }
  
          } else {
              addNew.style.display = "none";
          }
          if (!choiceList.querySelectorAll(".is-highlighted").length) {
              console.log("ASDF")
  
              addNew.classList.add("is-highlighted", "choices__item--selectable");
          }
      })
  
      obj.input.element.addEventListener('keydown', function (e) {
  
          var code = (e.keyCode ? e.keyCode : e.which);
  
          if (code == 13 && addNewAllowed()) {
              addItem();
              e.preventDefault()
              e.stopPropagation()
              return false;
          }
      })
  
      function addNewAllowed() {
          let choices_found = obj._currentState.choices.filter(elm => elm.label == obj._currentValue).length
          let items_found = obj._currentState.items.filter(elm => elm.label == obj._currentValue).length
          return (choices_found + items_found) == 0 && obj._currentValue != '';
      }
  
      function addItem() {
  
          obj.removeHighlightedItems();
          obj._currentState.choices.map(elm => elm.active = false)
          obj.input.element.value = ''
  
          obj._addChoice({
              value: obj._currentValue,
              label: obj._currentValue,
              isSelected: true,
              isDisabled: false
          });
  
          obj.input.element.dispatchEvent(new Event('keyup'));
  
      }
  }
  choicesjs_allow_create(choisesObjVariable) 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Pull request that adds new functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet