Select2: Select2 inside a scrolling container

Created on 7 Apr 2015  路  3Comments  路  Source: select2/select2

Hello, nice plugin!

I'm trying to use this plugin inside a container with height: 400px; and overflow: scroll but when I scroll the div while the dropdown is opened, it stays fixed in the same position of where it was before the scroll.

Is there some way to fix it?

Thanks.

troubleshooting

Most helpful comment

The dropdown position is defined by the calculation of css top and left value with this function :

AttachBody.prototype._positionDropdown = function () {...}//arround line 4235 in v.4.0.3

Let's say your container looks like this sample left menu :

<div class="left-colum">
  <ul>
    <li>
       <select>
         <option></option>
         <option></option>
       </select>
    </li>
    <li>
       <select>
         <option></option>
         <option></option>
       </select>
    </li>
  </ul>
</div>

```css
.left-column{
position:sticky;
top:60px;
height:400px;
overflow:scroll;
}

To achieve your needs, I suggest you could Initialize Select2 with `dropdownParent` option.
For example, you can find the closest element of each select, and assigned it to the `dropdownParent` option.
```javascript
$('.left-column').find('select').each(function(index,element){
  var parent = $(element).closest('li');
   $(element).select2({
        placeholder: '',
        allowClear: true,
        minimumResultsForSearch: 10,
        dropdownParent: $(parent)
  });
});

Then, when you scroll the .left-column, the opened dropdown should follow...

If the opened dropdown follow the scroll, you may notice that the more you scroll, the more the dropdown moves away. Not while scrolling, but while opening the dropdown after you scroll.
This is due to the calculation of the container offset applied to css top property.
At this point, I suggest you a short trick I used in the function :

AttachBody.prototype._positionDropdown = function () {...}//arround line 4235 in v.4.0.3

This worked for me in v.4.0.3
Near the end of the function, you should see :

    if (newDirection != null) {
      this.$dropdown
        .removeClass('select2-dropdown--below select2-dropdown--above')
        .addClass('select2-dropdown--' + newDirection);
      this.$container
        .removeClass('select2-container--below select2-container--above')
        .addClass('select2-container--' + newDirection);
    }

    this.$dropdownContainer.css(css);
  };

Just before this, you could add this :

    if (this.$dropdownParent == this.options.get('dropdownParent')) {
        var css = {
          'position':'relative',
          'display':'block',
          'top':'unset',
          'z-index': '2',
        };
        newDirection = 'below';
    }

This will apply those custom css when using the dropdownParent option.
Like that, the dropdown container should be at the expected position.

All 3 comments

The dropdown position is defined by the calculation of css top and left value with this function :

AttachBody.prototype._positionDropdown = function () {...}//arround line 4235 in v.4.0.3

Let's say your container looks like this sample left menu :

<div class="left-colum">
  <ul>
    <li>
       <select>
         <option></option>
         <option></option>
       </select>
    </li>
    <li>
       <select>
         <option></option>
         <option></option>
       </select>
    </li>
  </ul>
</div>

```css
.left-column{
position:sticky;
top:60px;
height:400px;
overflow:scroll;
}

To achieve your needs, I suggest you could Initialize Select2 with `dropdownParent` option.
For example, you can find the closest element of each select, and assigned it to the `dropdownParent` option.
```javascript
$('.left-column').find('select').each(function(index,element){
  var parent = $(element).closest('li');
   $(element).select2({
        placeholder: '',
        allowClear: true,
        minimumResultsForSearch: 10,
        dropdownParent: $(parent)
  });
});

Then, when you scroll the .left-column, the opened dropdown should follow...

If the opened dropdown follow the scroll, you may notice that the more you scroll, the more the dropdown moves away. Not while scrolling, but while opening the dropdown after you scroll.
This is due to the calculation of the container offset applied to css top property.
At this point, I suggest you a short trick I used in the function :

AttachBody.prototype._positionDropdown = function () {...}//arround line 4235 in v.4.0.3

This worked for me in v.4.0.3
Near the end of the function, you should see :

    if (newDirection != null) {
      this.$dropdown
        .removeClass('select2-dropdown--below select2-dropdown--above')
        .addClass('select2-dropdown--' + newDirection);
      this.$container
        .removeClass('select2-container--below select2-container--above')
        .addClass('select2-container--' + newDirection);
    }

    this.$dropdownContainer.css(css);
  };

Just before this, you could add this :

    if (this.$dropdownParent == this.options.get('dropdownParent')) {
        var css = {
          'position':'relative',
          'display':'block',
          'top':'unset',
          'z-index': '2',
        };
        newDirection = 'below';
    }

This will apply those custom css when using the dropdownParent option.
Like that, the dropdown container should be at the expected position.

This appears to be a usage question, rather than a bug report or feature request. Please see our contributing guidelines.

Usage questions should be discussed on the forums instead.

@vhanahrni - you saved my day!!!! Thumbs up! Additionally i needed to force the position of the dropdown at the bottom - realized that via https://stackoverflow.com/questions/19983601/prevent-select2-from-flipping-the-dropdown-upward - many thanks to andreivictor too

Was this page helpful?
0 / 5 - 0 ratings