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

Is tagging via <input> elements no longer supported? #3022

Closed
philipwalton opened this issue Feb 7, 2015 · 13 comments

Comments

Projects
None yet
8 participants
@philipwalton
Copy link

commented Feb 7, 2015

Here's an example of this not working. It used to work in 3.5.2:
http://jsbin.com/yonavaqiva/2/edit?html,output

Is this no longer supported or is this just something that needs to be worked out prior to the 4.0.0 release? FWIW, my use-case actually requires a comma-separated input rather than a multiselect.

@kevin-brown

This comment has been minimized.

Copy link
Member

commented Feb 7, 2015

Select2 4.0 does not support hidden input tags anymore, as we have decided to use the native <select> inputs for all options.

https://select2.github.io/announcements-4.0.html#hidden-input

You can add support back in through the use of a custom data adapter, I would recommend looking at the standard one for <select> tags as a base to work from. If you are able to get it working, either as a decorator or new adapter, we are interested in incorporating it into the core through a pull request.

@kevin-brown kevin-brown closed this Feb 7, 2015

@philipwalton

This comment has been minimized.

Copy link
Author

commented Feb 7, 2015

I wasn't asking about a hidden input tag, I was asking about regular input tag.

Select2 is supposed to be progressive enhancement, right? So if for whatever reason select2 fails to load, the "regular" form controls are supposed to just work fine.

In my case, I actually do want a regular <input> field. I don't want a <select multiple> field. The reason is the value of the input is actually supposed to be a comma-separated string and not an array (which is what you get with <select multiple>).

Are you saying select2 no longer supports <input> fields at all? If so I think that's a shame as this is a common use-case. It'd be a pain to require two separate plugins (with varying UIs) for very similar tasks.

@kevin-brown

This comment has been minimized.

Copy link
Member

commented Feb 7, 2015

I wasn't asking about a hidden input tag, I was asking about regular input tag.

They're the same thing to Select2 (that is, not an <select>). Select2 previously worked on a text box because both input[type=text] and input[type=hidden] both have the same properties.

Are you saying select2 no longer supports fields at all?

Not by default. This required extensive branching in the code to support both previously. Just to reinforce what I said previously

You can add support back in through the use of a custom data adapter, I would recommend looking at the standard one for <select> tags as a base to work from. If you are able to get it working, either as a decorator or new adapter, we are interested in incorporating it into the core through a pull request.

If you extended directly from the base <select> adapter, you would specifically need to override...

  • current - used like initSelection to convert the value to a set of data objects
  • select- called when a result is selected, you just need to append the id to the value attribute of the input
  • unselect - called when a result is unselected, you need to remove the id from the value attribute
  • query - similar to the old query method, used to get the results list
@kevin-brown

This comment has been minimized.

Copy link
Member

commented Feb 10, 2015

I'm actually going to tentatively reopen this for 4.0 while I coordinate with the Drupal team on a decent middle ground.

Relevant Drupal ticket: https://www.drupal.org/node/2346973

@kevin-brown kevin-brown reopened this Feb 10, 2015

@kevin-brown kevin-brown added this to the 4.0 milestone Feb 10, 2015

@wimleers

This comment has been minimized.

Copy link

commented Feb 16, 2015

Thanks for your comment on the Drupal issue! That helped us find this GitHub issue. (For those wondering, @kevin-brown's exact comment there can be found here: https://www.drupal.org/node/2346973#comment-9624861.)

I've replied there with our perspective/details, and I hope we can indeed find a decent middle ground. We completely understand your reasons for removing input[type=hidden] support, but we also would like to see input[type=text] support restored.


For the sake of simplifying/streamlining the conversation, I'm transplanting my comment there to this issue too:

That's awesome news! Thank you!

Basically, all there is to know is this:
  1. Drupal has supported "free tagging" (also known as folksonomies) for … 10 years or so. You can type any tag you want, and type a comma to indicate a next one.
  2. To help users find/select existing tags, there is an autocomplete, which takes the space-trimmed string after the last comma — if any — and asks the server for autocomplete matches. (It's never been quite as awesome as Select 2 though :)) i.e. foo, bar, baz -> "baz" is being autocompleted.
  3. To type tags containing commas, we wrap them in double quotes. i.e. Some Person, "Leers, Wim", Another Person has 3 tags: "Some Person", "Leers, Wim" and "Another Person". (This behavior would probably need to be implemented on the Drupal side, which is exactly what @amateescu did in #66, until @nod_ remarked in #69 that Select2 version 4 was about to be released, and this issue kind of got stuck on what to do now that Select2 no longer natively supports input[type=text]. In other words: you probably wouldn't even have to care, as long as we can still make it work just like we did for Select2 version 3.)
  4. Most importantly to you: what is described above, including the examples, are exactly what is sent to the server (commas, quotes, spaces and all). Basically, our UI has always been input[type=text] with some UI additions for autocompletion that helped the user get data in there in input[type=]text] faster and more easily — hence degrading "gracefully" to a very unhelpful, autocompleteless, mindblowingly simple UI: the plain input[type=text].
@theodoreb

This comment has been minimized.

Copy link

commented Feb 17, 2015

One way to solve this issue without major rearchitecturing would be to replace inputs by selects and get an event/callback in there to update the input value based on serialization rules. I'm pretty sure that's how we'd have done on it drupal side.

That would mean that parsing and serializing values get back in scope for select2 though.

@kevin-brown

This comment has been minimized.

Copy link
Member

commented Feb 17, 2015

The biggest challenge that I've been facing with this is what should be done when the value of the <input /> is updated.

Right now we can easily re-pull the text and value from the <option> tags and convert those to data objects. In the past we had a initSelection method that handled this, but it was specific to <input /> and poorly named.

I'm going to create a pull request locally (shortly) with the backwards compatibility adapters and what I've currently got.

kevin-brown added a commit that referenced this issue Feb 17, 2015

Added compatibility with `<input />` tags
This adds backwards compatibility back into Select2 for `<input />`
tags.  The compatibility modules are only available in the full
version and will trigger a warning if a hidden input is being used.

With the new decorator, Select2 should support the basic operations
that it previously did, with the exception of completely overriding
the internal objects. As we no longer expose `data` as a writable
method, it is no longer possible to completely override the selected
data. The state is still managed internally, but in order to prevent
data corruption issues in the past, it is not exposed to the public.

Some small changes needed to be made to how Select2 was dynamically
generating new `<option>` tags, so now a method is called that can
be overridden. In the case of the new decorator, this method is
intercepted and handled without having to actually place the
`<option>` tags into the DOM.

The decorator is applied after all of the other defaults, as the
defaults are not given the current element.

There has only been limited testing with this decorator, primarily
using the `data` and `placeholder` options.

This closes #3022.

@kevin-brown kevin-brown self-assigned this Feb 17, 2015

@wimleers

This comment has been minimized.

Copy link

commented Feb 27, 2015

Is there anything else you need from the Drupal side?

@kevin-brown

This comment has been minimized.

Copy link
Member

commented Feb 27, 2015

@wimleers I'm planning on rebasing the PR and merging it this weekend, along with doing the rc.1 release. There isn't anything else left for this on the Drupal side until it goes into further testing.

kevin-brown added a commit that referenced this issue Feb 27, 2015

Added compatibility with `<input />` tags
This adds backwards compatibility back into Select2 for `<input />`
tags.  The compatibility modules are only available in the full
version and will trigger a warning if a hidden input is being used.

With the new decorator, Select2 should support the basic operations
that it previously did, with the exception of completely overriding
the internal objects. As we no longer expose `data` as a writable
method, it is no longer possible to completely override the selected
data. The state is still managed internally, but in order to prevent
data corruption issues in the past, it is not exposed to the public.

Some small changes needed to be made to how Select2 was dynamically
generating new `<option>` tags, so now a method is called that can
be overridden. In the case of the new decorator, this method is
intercepted and handled without having to actually place the
`<option>` tags into the DOM.

The decorator is applied after all of the other defaults, as the
defaults are not given the current element.

There has only been limited testing with this decorator, primarily
using the `data` and `placeholder` options.

This closes #3022.
@aajahid

This comment has been minimized.

Copy link

commented May 2, 2016

Seems like this issue isn't fixed!

Here is a jsfiddle that shows same code applied on both <input /> and <select> to get tags feature.
https://jsfiddle.net/h5baz3bo/

The <select> tag works but <input /> doesn't!

Requesting to reopen the issue.
Thanks.

@narbsy

This comment has been minimized.

Copy link

commented Nov 27, 2016

I investigated this for a bit since my use case was to use an input[type='text'] element and select2 to provide some autocomplete support.

The InputData wrapper prevents this use case from correctly functioning, and there does not seem to be a good way to turn it off by default.

Locally, I tested this by commenting out the decoration of the dataAdapter with an InputData for input elements.

So, definitely think there's something incorrect with the compat layer here.

It would be nice to make it optional so that using a custom dataAdapter can override the compat behavior.

@lingceng

This comment has been minimized.

Copy link

commented Jul 18, 2017

I wrote a gist to make select2 tags work with text input.
As @theodoreb said:

One way to solve this issue without major rearchitecturing would be to replace inputs by selects and get an event/callback in there to update the input value based on serialization rules.

function select2InputTags(queryStr) {
  var $input = $(queryStr)

  var $select = $('<select class="'+ $input.attr('class') + '" multiple="multiple"><select>')
  if ($input.val() != "") {
    $input.val().split(',').forEach(function(item) {
      $select.append('<option value="' + item + '" selected="selected">' + item + '</option>')
    });
  }
  $select.insertAfter($input)
  $input.hide()

  $select.change(function() {
    $input.val($select.val().join(","));
  });

  return $select;
}

https://gist.github.com/lingceng/d1cd5ca5db9a777b31487769242c422f.js

See the demo here: https://jsfiddle.net/lingceng/h5baz3bo/13/
It's simple to use:

select2InputTags('#select2Input').select2({
       tags: true, // Doesn't work either
       // tags:["red", "green", "blue"], // Doesn't work either
       multiple: true,
       tokenSeparators: [",", " "]
});

I'd like to make it a repo if you like it.

@konstruktur

This comment has been minimized.

Copy link

commented Mar 21, 2019

thanks @lingceng for this helpful gist!

I just noticed some troubles with reloading fields with select2InputTags(). I work with a webquestionnaire tool (limesurvey) and use select2 4.0.5 to augment the textfields with multiselect and tagging. I just noticed, that when I fill in a field (select2 with select2InputTags), change page (one question per page) and come back the values (saved in the text fields) are reloaded, but it shows only the id, not the text.

So if I have 4 Options and loading them from an array:

var qID = {QID};  /* identify question in the survey */
var wordList1=[ { id: 1, text: 'Option 1' }, { id: 2, text: 'Option 2' }, { id: 3, text: 'Option 3' }, { id: 4, text: 'Option 4' } ];  /* create options for the select2 field */

$('#question'+qID+' input[type="text"]').each(function(i) {
	select2InputTags($(this)).select2({ 
		data: wordList1, width: '95%', 
		minimumResultsForSearch: -1, 
		tags: true, 
		tokenSeparators: [','], 
		placeholder: "...", 
		multiple: true, 
		debug: true
		}); 
	});
  1. I choose Option 1, Option 2 and type some text 'asdfg'.
  2. I go forth to the next page and come back
    3a) the preloaded content for the text field is '1','2','asdfg' - so it only shows the ids, not the text.
    3b) the dropdown text for options '1' and '2' is also replaced by the id, e.g. there is no 'Option 1' in the dropdown, but only '1' . (In this case it's '1', '2', 'asdfg', 'Option 3', 'Option 4')

I created a gist at https://jsfiddle.net/konstruktur/2oay3r9x/15/, but it can't show this pagechange and I unfortunately can't give a reproducible example, since I cannot give access to my installation of the survey software, but maybe someone, maybe @lingceng knows how to get the id and text (instead of the id only) on reload and can adapt this great gist? Thanks a lot for your time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.