Ember-power-select: Dropdown positioning problem

Created on 17 Feb 2016  路  10Comments  路  Source: cibernox/ember-power-select

When component is not rendered in place, dropdown is appended to div with id ember-basic-dropdown-wormhole which is added to body. In my use case, body is not scrollable and a section of the body is scrollable in which power select is used. In this scenario when scrollable section is scrolled, trigger scrolls with the scrollable section, but dropdown doesn't scroll along with trigger as it is positioned absolute(parent element is body). If select is at the bottom of the section and rendered in place, dropdown goes down(There is no auto positioning for render in place).

Most helpful comment

I'm posting in this old issue as none of the options work for me.

I have a panel that has an outlet, but my outlet is in a liquid-outlet so renderInPlace and destination both don't work because the height of the outlet is defined by by liquid-fire. The results get cut off by the overflow and destination doesn't work because it's getting it's offset from the window left and not from it's containing element, as it exists in a liquid-outlet it has position:absolute; on the container, so I was going to force the no scroll using the css posted above for the wormhole container, but .is-dropdown-open is never added to the container.

Does anyone have a way forward?

All 10 comments

@nhemanth007 @cibernox Here is my suggestion.

Normal browser select won't allow you to scroll when it is open until you select some option or close it.

We can achieve similar behaviour if body is locked down to available browser height. When the dropdown is open #ember-basic-dropdown-wormhole element can have following css properties to prevent any other scrolls until the power select is closed.

#ember-basic-dropdown-wormhole.is-dropdown-open {
  position:absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 999;  // less than dropdown z-index to have it on top.
}

P.S: this seems to be an extreme hack. Any better solutions?

Yes, I've updated the docs showing how to customize this: https://ember-power-select.pagefrontapp.com/docs/the-list

I think that in your case since the app is not scrollable but some element inside, that could be fixed if instead of insertig the content of the select in a child of the body, you attach it to a child of the element of the element that has the scroll. Perhaps you need to make the element that contains the scroll position: relative, but I think that this might work

ENV['ember-basic-dropdown'] = {
  destination: 'power-select-render-target'
}
<div class="main-content-with-scroll">
  {{outlet}}
  <div id="power-select-render-target"></div>
</div>

You need to update to the very last version of the component to do that.

Makes sense?

I think it works if all the drop downs using power select are present in the same scrollable element in a page. What if there are multiple scrollable elements in a page and power select has to used in each of them(which is my current use case)?

I just pushed a new version that allows you to customize the destination element of the selects on a per component basis: {{#power-select destination="my-unique-destination" ... as |thing|}}

I don't know if it will work tho, because some position calculation are in base to the entire page, so perhaps it's not "scrollable" friendly.

Let me know if any of this works. I never had this use case myself.

The alternative would be make the renderInPlace have automatic positioning. That wouldn't be trivial but I think that is doable.

I have a select in modal and the dropdown actual renders being the modal overlay. Is there a technical reason for rendering the dropdown in a totally separate DOM element (aka ember-basic-dropdown-wormhole)?

My first reaction is that it should belong to the same DOM parent you defined. Every time I have used components that try to be smart about z-index and positioning by decoupling themselves from where they actually belong, it led to more problems than it solved.

I can see why overflow: hidden on a parent could be a pita but maybe it should be up to the user to actually move the dropdown out in that specific situation. wdyt?

@karellm You can do it. The default is render it in the root of the body (is the safe default), but you can opt out to this passing renderInPlace=true. The default is to render it in the root of the body intentionally, because is the safest choice.

Also worth mention that the z-index of the dropdown is 1000 intentionally, so modals (that usually have a z-index of 1050) render above it.

Why? Because if a modals can open unexpectedly while a dropdown is opened (as a result of a push notification by example) and in those cases you don't want to have the dropdown floating over the modal. However, having a dropdown inside a modal is something you do intentionally, and in those cases you can be prepared, either rendering in place or adding a special class to that dropdown that gives it a higher z-index, or even passing a different wormholeDestination property so it is added somewhere else instead of in the root of the body.

There is plenty of options to get the desired behaviour.

Makes sense, thanks for the clarification.

I'm posting in this old issue as none of the options work for me.

I have a panel that has an outlet, but my outlet is in a liquid-outlet so renderInPlace and destination both don't work because the height of the outlet is defined by by liquid-fire. The results get cut off by the overflow and destination doesn't work because it's getting it's offset from the window left and not from it's containing element, as it exists in a liquid-outlet it has position:absolute; on the container, so I was going to force the no scroll using the css posted above for the wormhole container, but .is-dropdown-open is never added to the container.

Does anyone have a way forward?

@evoactivity same problem here

Was this page helpful?
0 / 5 - 0 ratings