ConfirmPopup: misplaced / missing popup on stopped click event
Describe the bug
If the event which caused the popup to appear is stopped from propagating up to the root window, the popup is misplaced, or does not even appear, depending on whether the popup is already displayed when the event occurs.
When clicking Save, no popup appears:
When clicking Delete then Save, the popup is misplaced, as the arrow still points to Delete:
the Popover component does not exhibit the same issue.
Reproducer
stackblitz is down at the time of writting this issue
PrimeVue version
4.0.0-rc.2
Vue version
3.x
Language
TypeScript
Build / Runtime
Nuxt
Browser(s)
No response
Steps to reproduce the behavior
This can be reproduced by applying this patch to the documentation example, going to http://localhost:3000/confirmpopup/#basic, then clicking Save:
diff --git a/apps/showcase/doc/confirmpopup/BasicDoc.vue b/apps/showcase/doc/confirmpopup/BasicDoc.vue
index 241061c89..bf8725176 100644
--- a/apps/showcase/doc/confirmpopup/BasicDoc.vue
+++ b/apps/showcase/doc/confirmpopup/BasicDoc.vue
@@ -4,7 +4,7 @@
</DocSectionText>
<ConfirmPopup></ConfirmPopup>
<div class="card flex flex-wrap gap-2 justify-center">
- <Button @click="confirm1($event)" label="Save" outlined></Button>
+ <Button @click.stop="confirm1($event)" label="Save" outlined></Button>
<Button @click="confirm2($event)" label="Delete" severity="danger" outlined></Button>
</div>
<DocSectionCode :code="code" />
Expected behavior
The ConfirmPopup should always show up, and be correctly placed.
On safari the popup is misplaced more often even without the stop but I noticed that a second click on the button that would call confirm.require would make the popup move from the top left to the correct position so I dove into the code.
It looks like the alignOverlay method is only called in the outside click handler: https://github.com/primefaces/primevue/blob/8d8ca02bd375b565d99e02cb92831da6699c22d0/components/lib/confirmpopup/ConfirmPopup.vue#L199-L209
The only reason the popup would show up in the correct place is if the target is set and after that the outside click listener is triggered. Thus when we stop the propagation the outside click listener is not triggered and the popup is never aligned.
So I adding a call to alignOverlay when making the popup visible should solve this issue
+1, currently blocking by this when stopping propagation for a "remove" icon that is the children of another element that have a click handler.
The issue also arises when row click is enabled in the datatable and a button is placed inside one of the columns (which is another problem). In this scenario, you need to apply stopPropagation on the button to prevent the row click event from triggering, but this can cause the confirmation pop-up to appear in an incorrect location.
On safari the popup is misplaced more often even without the stop but I noticed that a second click on the button that would call
confirm.requirewould make the popup move from the top left to the correct position so I dove into the code.It looks like the
alignOverlaymethod is only called in the outside click handler:https://github.com/primefaces/primevue/blob/8d8ca02bd375b565d99e02cb92831da6699c22d0/components/lib/confirmpopup/ConfirmPopup.vue#L199-L209
The only reason the popup would show up in the correct place is if the target is set and after that the outside click listener is triggered. Thus when we stop the propagation the outside click listener is not triggered and the popup is never aligned.
So I adding a call to
alignOverlaywhen making the popup visible should solve this issue
Thank you! The workaround that seems to work for me is applying focus to the current element just before triggering the confirmation popup. 'event.currentTarget' seems to be undefined on click so i'm using the 'event.target' one:
const confirm = (event) => {
event.target.focus(); // focus the clicked element so the alignOverlay function triggers
confirm.require({
target: event.currentTarget, //does this even do anything??
message: 'Are you sure?,
icon: 'pi pi-info-circle',
rejectProps: {
label: 'No!',
severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Yes',
severity: 'danger'
},
accept: () => {
// submitting by pressing the 'enter' key doesn't always close the confirm box, so the close method makes sure it closes properly
confirm.close();
}
});
};
for some reason target.focus() didn't help
but this ugly nextTick does the job
Please try to use the latest version. It seems the problem was solved.
Thank you!
For the ones still having this issue (while using V3) for me this worked:
nextTick(() => target.click());
confirm.require({ target, .... })
For the ones still having this issue (while using V3) for me this worked:
nextTick(() => target.click()); confirm.require({ target, .... })
Just saved me hours of pain, thanks man