PrimeNG Tree D&D Droppoint CSS customisation: regression
Describe the bug
Hello,
We have CSS on PrimeNG tree droppoint setting height.
I have some changes to offer, but you may not want all of them, then I opted to create this ticket instead of a PR.
Upgrading to version 21.1.1, we found a regression customizing the droppoint introduced in this commit.
The droppoint used to be full time visible, and is now conditionned on first 25% for previous droppoint and last 25% for after droppoint.
How to reproduce (extraction):
.tree { .p-tree-node-drop-point { height: 50px; }}
Issue 1
Opening previous droppoint leads to exiting the first 25% and close droppoint. Also leaving node to opened next droppoint leads to the same issue.
Fix :
- Identify event for previous/next droppoint
- Manage exit node on top/bottom/side according the the node
- Add events on droppoint
- (dragleave)="onNodeDragLeave()"
(dragleave)="onNodeDragLeave($event)"- onNodeDragLeave() {
- this.isPrevDropPointHovered.set(false);
- this.isNextDropPointHovered.set(false);
onNodeDragLeave(event: any) {
let rect = event.currentTarget.getBoundingClientRect();
if (
event.x > rect.left + rect.width || // right leave
event.x < rect.left // left leave
) {
this.isPrevDropPointHovered.set(false);
this.isNextDropPointHovered.set(false);
}- <div [class]="cx('dropPoint')" [attr.aria-hidden]="true" [pBind]="getPTOptions('dropPoint')"></div>
<div
[class]="cx('dropPoint')"
[attr.aria-hidden]="true"
(dragleave)="onDropPointDragLeave($event, 'previous')"
(drop)="onDropPoint($event, 'previous')"
[pBind]="getPTOptions('dropPoint')"
></div>- <div [class]="cx('dropPoint', { next: true })" [attr.aria-hidden]="true" [pBind]="getPTOptions('dropPoint')"></div>
<div
[class]="cx('dropPoint', { next: true })"
[attr.aria-hidden]="true"
(dragleave)="onDropPointDragLeave($event, 'next')"
(drop)="onDropPoint($event, 'next')"
[pBind]="getPTOptions('dropPoint')"
></div> onDropPoint(event: any, _position : string) {
this.onNodeDrop(event);
}
onDropPointDragLeave(event: any, position : string) {
let rect = event.currentTarget.getBoundingClientRect();
if (position === 'previous' && event.y < Math.floor(rect.top + rect.height)) {
this.isPrevDropPointHovered.set(false);
}
if (position === 'next' && event.y >= rect.top) {
this.isNextDropPointHovered.set(false);
}
}Issue 2
Index returned by drop event is not the same between node A and node B but is visually the same. This may not be mandatory, but leads to confusion for users. (We used to hide one of the droppoint to avoid this management)
Fix: return same index for visual droppoint
if (isValidDrop) {
+ const newIndex : number | undefined = (this.index && position === -1) ? this.index - 1 : this.index
if (this.tree.validateDrop) {
this.tree.onNodeDrop.emit({
originalEvent: event,
dragNode,
dropNode: this.node,
- index: this.index,
+ index: newIndex,Issue 3
Now if I go too fast while D&D, I sometimes have severals droppoints that does not got their onDropPointDragLeave.
Fix: introduce delayed event to hide droppoint if more than one is visible.
Note: May not be the solution wanted by PrimeNG team.
static cleanDroppoint: number;
private delayedCleanNodeDropPoints(event : any) : void {
clearTimeout(UITreeNode.cleanDroppoint);
UITreeNode.cleanDroppoint = window.setTimeout(() => {
this.cleanNodeDropPoints(event);
}, 10);
}
private cleanNodeDropPoints (event : any) : void {
let parent : ParentNode | null = event.target.parentNode;
while (parent !== null && parent.nodeName !== 'APP-CUSTOM-PRIME-TREE') {
parent = parent.parentNode;
}
if (parent) {
const nodes : NodeListOf<Element> = parent.querySelectorAll('.p-tree-node-drop-point');
if (nodes.length > 1) {
nodes.forEach((droppoint : Element) => droppoint.remove())
}
}
}This is open to discussion.
I'll try to create a Stackbitz to help you with this feedback. Right know can't make d&d work.
If you agree with all those changes, I may have time to create PR, please let me know.
Here is what we have on our project with the fixes (and more CSS): https://github.com/user-attachments/assets/8ef3b539-d67d-4290-91bf-018dff7962bb
BTW, thats for the work
Pull Request Link
No response
Reason for not contributing a PR
- Lack of time
- Unsure how to implement the fix/feature
- Difficulty understanding the codebase
- Other
Other Reason
No response
Reproducer
https://stackblitz.com/edit/github-l3djqppz?file=src%2Fapp%2Fapp.component.css
Environment
"@angular/...": "^21.0.0",
"primeicons": "^7.0.0",
"primeng": "^21.1.1",Angular version
21.1.1
PrimeNG version
v21
Node version
24
Browser(s)
Opera
Steps to reproduce the behavior
1- add CSS to set droppoint height, eventually backgroud color to have it clear. 2- drag & drop to display droppoint
Expected behavior
Droppoint should be customised. Drop index should be the same when visually the same.
Source: primefaces/primeng