How to render ComboBox/AutoComplete/MultiSelect popups inside a HTML dialog element?

Greetings,

We are using several EJ2 ComboBox/AutoComplete/MultiSelect components inside `<dialog>`s.

`<dialog>`s do render in the [top layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer), meaning that they show up on top of every other layer in the web page, no matter how high a `z-index` attribute can be set.

The problem we are facing with these components is that they render their popups as the latest child of the `<body>` element, so such component within a `<dialog>` will always render their popups *below* the top layer, meaning that it can't be accessible by any means, let alone completely misplaced.

So far I've done a workaround on this by setting something like

open: args => {

const popup = args.popup.element;

setTimeout(() => {

document.getElementById('my-dialog').appendChild(popup);

}, 0);

}

But this is more of a hit-and-miss method, since it will yield different results with ComboBox, AutoComplete or MultiSelect. And all of them are going to show misplaced.

However, recently I learned about the [`relateTo`](https://ej2.syncfusion.com/javascript/documentation/api/popup#relateto ) property of the Popup element, which in paper seems to solve this situation - but I just can't find how to set it or make it work (at least here, with EJ2 23.2.4) - should this set in the ComboBox/AutoComplete/MultiSelect in some way? For example the following won't work at all:

open: function(args) {

setTimeout(() => {

this.popupObj.relateTo = document.getElementById('<?=$slideoverId?>-include_records-popup');

}, 0);

}


3 Replies

YS Yohapuja Selvakumaran Syncfusion Team February 21, 2025 02:10 PM UTC

Hi Acidrums,


Thank you for reaching out to us. We understand that you would like to render Syncfusion's ComboBox, AutoComplete, MultiSelect, and DropDownList components inside a Dialog component.

To achieve this, you can dynamically initialize these components inside the open event of the Dialog, ensuring they render properly when the dialog is displayed. Below is a working example:

import { Dialog } from '@syncfusion/ej2-popups';
import { Button } from '@syncfusion/ej2-buttons';
import { DropDownList, ComboBox, AutoComplete, MultiSelect } from '@syncfusion/ej2-dropdowns';

// Define sample data
let dropdownData = [
    { id: '1', text: 'Option 1' },
    { id: '2', text: 'Option 2' },
    { id: '3', text: 'Option 3' }
];

let dialog = new Dialog({
    header: 'Select Options',
    content: `<label>DropDownList:</label> <input id="dropdown" />
              <label>ComboBox:</label> <input id="combobox" />
              <label>AutoComplete:</label> <input id="autocomplete" />
              <label>MultiSelect:</label> <input id="multiselect" />`,
    showCloseIcon: true,
    target: document.getElementById('container'),
    width: '435px',
    height: '76%',
    open: dialogOpen
});

dialog.appendTo('#dialog');

function dialogOpen(): void {
    new DropDownList({ dataSource: dropdownData, fields: { text: 'text', value: 'id' }, placeholder: 'Select an option' }).appendTo('#dropdown');
    new ComboBox({ dataSource: dropdownData, fields: { text: 'text', value: 'id' }, placeholder: 'Select or type' }).appendTo('#combobox');
    new AutoComplete({ dataSource: dropdownData, fields: { text: 'text', value: 'id' }, placeholder: 'Type to search' }).appendTo('#autocomplete');
    new MultiSelect({ dataSource: dropdownData, fields: { text: 'text', value: 'id' }, placeholder: 'Select multiple options' }).appendTo('#multiselect');
}


This implementation ensures that the dropdown components initialize only when the Dialog is opened, preventing any rendering issues. Please find the sample for your reference,

Samplehttps://stackblitz.com/edit/ynuvdmyw-6bsxwukn?file=index.ts


Regards,

Yohapuja S




AC acidrums4 February 21, 2025 02:26 PM UTC

Thank you and I really appreciate your response,

But I'm afraid this is not what I was asking for, in the sense that we don't want to append the DropdownList/ComboBox/AutoComplete to a EJ2 Dialog component, but an actual, native HTML `<dialog>` element. It's with this element that problems arise since the popups from the DropdownList/ComboBox/AutoComplete components are appended at the end of the `<body>` element rather than the `<dialog>` and, since the `<dialog>` is painted in the top layer, users will never be able to interact with the contents of the popup of those components.



YS Yohapuja Selvakumaran Syncfusion Team February 25, 2025 05:26 AM UTC

Hi acidrums,


We understand that you are using a native HTML <dialog> instead of the Syncfusion Dialog component, and the popups from the DropDownList, ComboBox, AutoComplete, and MultiSelect are being appended to the <body>, causing them to appear below the dialog.


To resolve this issue, we recommend adjusting the popup’s position dynamically in the open event of the components. Below is an updated approach where the popups are appended inside the dialog to ensure they appear above it:


[html]

 

<button id="openDialog">Open Dialog</button>

<dialog id="custom-dialog">
  <form method="dialog">
    <p>DropDownList: <input id="dropdown" /></p>
    <p>ComboBox: <input id="combobox" /></p>
    <p>AutoComplete: <input id="autocomplete" /></p>
    <p>MultiSelect: <input id="multiselect" /></p>
    <button type="submit">Close</button>
  </form>
</dialog>


[typescript]


import {
  DropDownList,
  ComboBox,
  AutoComplete,
  MultiSelect,
} from '@syncfusion/ej2-dropdowns';

const dialog = document.getElementById('custom-dialog') as HTMLDialogElement;
const openDialogButton = document.getElementById('openDialog');

openDialogButton.addEventListener('click', () => {
  dialog.showModal(); // Open the native dialog

  function adjustPopupPosition(component) {
    setTimeout(() => {
      if (component.popupObj) {
        const popupElement = component.popupObj.element;
        popupElement.style.zIndex = '10001'; // Ensure popup is above the dialog
        popupElement.style.position = 'absolute';
        dialog.appendChild(popupElement); // Move popup inside the dialog
      }
    }, 0);
  }

  // Initialize DropDownList
  let dropDownList = new DropDownList({
    dataSource: ['Option 1', 'Option 2', 'Option 3'],
    placeholder: 'Select an option',
    popupHeight: '200px',
    open: function () {
      adjustPopupPosition(this);
    },
  });
  dropDownList.appendTo('#dropdown');

  // Initialize ComboBox
  let comboBox = new ComboBox({
    dataSource: ['Option A', 'Option B', 'Option C'],
    placeholder: 'Type or select',
    popupHeight: '200px',
    open: function () {
      adjustPopupPosition(this);
    },
  });
  comboBox.appendTo('#combobox');

  // Initialize AutoComplete
  let autoComplete = new AutoComplete({
    dataSource: ['Apple', 'Banana', 'Cherry'],
    placeholder: 'Type to search',
    popupHeight: '200px',
    open: function () {
      adjustPopupPosition(this);
    },
  });
  autoComplete.appendTo('#autocomplete');

  // Initialize MultiSelect
  let multiSelect = new MultiSelect({
    dataSource: ['Red', 'Blue', 'Green'],
    placeholder: 'Select multiple',
    popupHeight: '200px',
    open: function () {
      adjustPopupPosition(this);
    },
  });
  multiSelect.appendTo('#multiselect');
});


Moves the popup inside the <dialog>, ensuring it's not hidden under the top-layer rendering. Dynamically adjusts the popup’s z-index and position for proper visibility. Uses setTimeout() to ensure the popup positioning executes after it is rendered. Please find the below sample for your reference.

Samplehttps://stackblitz.com/edit/ynuvdmyw-sb2naub1?file=index.ts,index.html



Regards,

Yohapuja S


Loader.
Up arrow icon