diff --git a/components/dialog/index.spec.ts b/components/dialog/index.spec.ts index 38e0e8c3c..bec4d1e02 100644 --- a/components/dialog/index.spec.ts +++ b/components/dialog/index.spec.ts @@ -337,6 +337,36 @@ describe('Dialog', () => { expect(dialog2.querySelector('.k-dialog-body')!.textContent).to.eql('test'); }); + it('should update position when change container', async () => { + class Demo extends Component<{show: boolean, container: any}> { + static template = ` + var Dialog = this.Dialog; + test + `; + + private Dialog = Dialog; + + static defaults() { + return { + container: (parentDom: HTMLElement) => parentDom, + }; + } + } + + const [instance, element] = mount(Demo); + + await wait(); + instance.set('container', undefined); + await wait(); + const dialogDom = instance.refs.dialog.dialogRef.value; + const style = dialogDom.style; + expect(style.left).not.eql(''); + expect(style.top).not.eql(''); + + // should append to body + expect(dialogDom.closest('.k-dialog-wrapper').parentElement).to.eql(document.body); + }); + // it('should handle v-if and v-model at the same time correctly in Vue', async () => { // const Test = { // template: `test`, diff --git a/components/dialog/usePosition.ts b/components/dialog/usePosition.ts index 278ff29d3..3b7296b2a 100644 --- a/components/dialog/usePosition.ts +++ b/components/dialog/usePosition.ts @@ -8,6 +8,10 @@ export function usePosition(elementRef: RefObject) { instance.on(SHOW, center); instance.on('afterClose', onAfterLeave); + instance.watch('container', () => { + if (!instance.get('value')) return; + center(); + }, { presented: true, inited: true }); function center() { position(elementRef.value!, { diff --git a/components/dropdown/usePosition.ts b/components/dropdown/usePosition.ts index d0d5b9db5..e2c1c0d40 100644 --- a/components/dropdown/usePosition.ts +++ b/components/dropdown/usePosition.ts @@ -1,8 +1,7 @@ import {useInstance, findDomFromVNode} from 'intact'; import type {Dropdown} from './'; import {Options, position, Feedback} from '../position'; -import {noop} from 'intact-shared'; -import {isObject} from 'intact-shared'; +import {noop, isObject, isFunction} from 'intact-shared'; import { isEqualObject } from '../utils'; export type FeedbackCallback = (feedback: Feedback) => void; @@ -19,21 +18,32 @@ export function usePosition() { (['of', 'position'] as const).forEach(item => { instance.watch(item, (newValue, oldValue) => { - // return if object is the same if ( + instance.get('value') || + // return if object is the same isObject(newValue) && isObject(oldValue) && // is not event object !(newValue instanceof Event) && isEqualObject(newValue, oldValue) - ) { - return; - } - if (instance.get('value')) { - handle(noop); - } + ) return; + + handle(noop); }, {presented: true, inited: true}); }); + // watch container, it is not commonly used + instance.watch('container', (newValue, oldValue) => { + if ( + !instance.get('value') || + // return if function is the same. Not rigorous! + isFunction(newValue) && + isFunction(oldValue) && + newValue.toString() === oldValue.toString() + ) return; + + handle(noop); + }, { presented: true, inited: true }); + // if the dropdown is nested, we must show child after parent has positioned function p( ofElement: HTMLElement | MouseEvent | undefined, diff --git a/components/portal.ts b/components/portal.ts index 6983998dc..22816cb97 100644 --- a/components/portal.ts +++ b/components/portal.ts @@ -151,7 +151,11 @@ export class Portal extends Component { } else { this.container = container(parentDom, anchor); } + } else { + // let below logic to set container to default if container does not exist. + this.container = null; } + if (!this.container) { if (this.$senior instanceof BaseDialog) { // Dialog and Drawer must be inserted into document.body