`containerCssClass` is applied to `.select2-selection` element

Hi guys,

I’m using select2 v4.0.5.
This code:

$select.select2({
  containerCssClass: 'myContainerCssClass'
});

generates the following markup for me:

24

As you might see myContainerCssClass was applied not to the root .select2-container element, but rather to nested .select2-selection.

My questions:

  1. Is it an expected behaviour or it’s a bug?
  2. If it’s an expected behaviour, is there a proper way to apply custom css class to the root .select2-container element which is a real container IMO?
    I’ve already seen that $select2.data('select2').$container.addClass("wrap") jazz here and I’m considering it a terrible workaround, rather than a proper solution. There should be a configuration key for that.

It looks like this is a pretty old issue, but I’m guessing that it’s probably the expected behavior.

If you can look at the commit history for the lines that process the containerCssClass option, we could trace it to see if there is any explanation from the developers.

The other possibility is to implement a custom SelectionAdapter, which might be able to manipulate the DOM on the container element. Someone recently posted a tutorial on their blog about how to implement custom adapters.

Hi,

same issue popped up here.

IMHO there is a fundamental problem in the current implementation of “ContainerCSS” - using the SelectionAdapter: the render() function is called before containers DOM is fully constructed. Although the container element already exists, the render function has not yet access to it (neither through elem.closest(’.select2’) nor through “this”). (*)

So, I adapted the ContainerCSS code and wrote a custom adapter: instead of render() it all happens in bind() - because when bind() is called all required things are available: the container is constructed and the Select2 member data is also fully constructed.

That was easy.

But now I am scratching my head…: what is the best (correct?) way to use/inject my custom adapter with/into the lib:

  1. as a default, in the same way that ContainerCSS was used - I’d like to keep all the features, like single/multi, placeholders, etc., I do not want to alter all existing elements and .select2() calls in my project (automatic placeholders, multi, etc. are promising and work fine so far)

  2. I dont want to write much setup code that would diverge from future select2 versions.

  3. To the point: Do I REALLY have to copy & paste the whole 240 lines from Defaults.prototype.apply just to insert my custom adaptor as a selectionAdapter (because I’d like to keep that standard decorator chain that is constructed there and thats what everyone else uses and whats proven) ???

  4. I am not quite sure that EVEN THAT is possible (without altering select2 itself of course)!

Lets say I connect my adapter using:
$.fn.select2.defaults.set(‘selectionAdapter’,$.fn.select2.amd.require(‘MyCustomSelectionAdapterChain’));

When writing a custom adapter as a module that combines standard adapters to a decorator chain, there still is a huge issue: the options are not available there (but they ARE in Defaults.prototype.apply). So, such a module can not (yet) decide e.g. whether to use Single- or MultipleSelection and whether to use Placeholders or not and so on. So it maybe should consist of a global and per-element setup path.

So, that would require more and more individual case decisions… and more code and more and more code…

But maybe I missed something? I am not a big fan of decorators and adapters (and most other structural patterns), so that may have dazzled me.

However: the actual problem could have been solved in about 10min, much easier, if select2() would provide a few more events and/or callbacks!

Having a “created” event would be a huge improvement! That would be nice.

(*) very bad, ugly, but still…: this.$element.nextAll(’.select2’) works.