Skip to content

Commit b402736

Browse files
authored
fix: ignore target set while popover is detached until re-attached (#8350)
1 parent a413851 commit b402736

File tree

2 files changed

+87
-11
lines changed

2 files changed

+87
-11
lines changed

packages/popover/src/vaadin-popover-target-mixin.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,32 @@ export const PopoverTargetMixin = (superClass) =>
3434
*/
3535
target: {
3636
type: Object,
37-
observer: '__targetChanged',
37+
},
38+
39+
/** @private */
40+
__isConnected: {
41+
type: Boolean,
42+
sync: true,
3843
},
3944
};
4045
}
4146

47+
static get observers() {
48+
return ['__targetOrConnectedChanged(target, __isConnected)'];
49+
}
50+
4251
/** @protected */
4352
connectedCallback() {
4453
super.connectedCallback();
4554

46-
if (this.target) {
47-
this._addTargetListeners(this.target);
48-
}
55+
this.__isConnected = true;
4956
}
5057

5158
/** @protected */
5259
disconnectedCallback() {
5360
super.disconnectedCallback();
5461

55-
if (this.target) {
56-
this._removeTargetListeners(this.target);
57-
}
62+
this.__isConnected = false;
5863
}
5964

6065
/** @private */
@@ -82,14 +87,16 @@ export const PopoverTargetMixin = (superClass) =>
8287
}
8388

8489
/** @private */
85-
__targetChanged(target, oldTarget) {
86-
if (oldTarget) {
87-
this._removeTargetListeners(oldTarget);
90+
__targetOrConnectedChanged(target, isConnected) {
91+
if (this.__previousTarget && (this.__previousTarget !== target || !isConnected)) {
92+
this._removeTargetListeners(this.__previousTarget);
8893
}
8994

90-
if (target) {
95+
if (target && isConnected) {
9196
this._addTargetListeners(target);
9297
}
98+
99+
this.__previousTarget = target;
93100
}
94101

95102
/**

packages/popover/test/basic.test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,75 @@ describe('popover', () => {
374374
});
375375
});
376376

377+
describe('detach and re-attach', () => {
378+
let target;
379+
380+
beforeEach(() => {
381+
target = fixtureSync('<button>Target</button>');
382+
});
383+
384+
it('should not open on target click when detached', async () => {
385+
popover.target = target;
386+
await nextUpdate(popover);
387+
388+
popover.remove();
389+
target.click();
390+
391+
expect(popover.opened).to.be.false;
392+
});
393+
394+
it('should open on target click when re-attached', async () => {
395+
popover.target = target;
396+
await nextUpdate(popover);
397+
398+
popover.remove();
399+
400+
target.parentNode.appendChild(popover);
401+
await nextUpdate(popover);
402+
403+
target.click();
404+
405+
expect(popover.opened).to.be.true;
406+
});
407+
408+
it('should not open on target click when target set while detached', async () => {
409+
popover.remove();
410+
411+
popover.target = target;
412+
await nextUpdate(popover);
413+
414+
target.click();
415+
416+
expect(popover.opened).to.be.false;
417+
});
418+
419+
it('should open when target set while detached after re-attached', async () => {
420+
popover.remove();
421+
422+
popover.target = target;
423+
await nextUpdate(popover);
424+
425+
target.parentNode.appendChild(popover);
426+
await nextUpdate(popover);
427+
428+
target.click();
429+
430+
expect(popover.opened).to.be.true;
431+
});
432+
433+
it('should not open on target click when target is cleared', async () => {
434+
popover.target = target;
435+
await nextUpdate(popover);
436+
437+
popover.target = null;
438+
await nextUpdate(popover);
439+
440+
target.click();
441+
442+
expect(popover.opened).to.be.false;
443+
});
444+
});
445+
377446
describe('dimensions', () => {
378447
function getStyleValue(element) {
379448
return element

0 commit comments

Comments
 (0)