We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Problem with row reorder (drag-and-drop row reorder ... same treeGrid)

Hello guys,

I have the following issue:


After successfully reordering the row like in the picture I'm stuck with that image near my cursor and I can not shake it off :(

in onRowDropp I am doing some validation and after the validation, I'm doing a post to an API and then subscribing to get​ some response and populate the tree again with the new data all this works very well I might add but I get that nasty div of the selected stuff stuck near my cursor and would not go away.

PS: I did do a document.getElementByStyle() and deleted the div but after that, I get a lot of errors in the console (syncfusion does not want that deleted :( ); I also tried hiding that but gets visible immediately as I move the cursor :(



6 Replies

FS Farveen Sulthana Thameeztheen Basha Syncfusion Team October 13, 2022 02:25 PM UTC

Hi AlexB,


We have checked your reported problem with RowDraganddrop on Reordering rows but we are unable to replicate the problem at our end. Refer to the sample link:-

https://stackblitz.com/edit/angular-gqu5jt?file=app.component.html


Before proceeding this, we need some more additional details to find the cause of the issue. Share us the following details.


  1. Complete TreeGrid code example.
  2. Have you faced the issue after reloading the new Data. Share us the video demo to replicate the issue.
  3. If possible replicate it in the above sample and revert us back.
  4. Detail explanation of exact scenario you have faced the issue.
  5. Syncfusion TreeGrid package version details.


Regards,

Farveen sulthana T



AL AlexB October 14, 2022 10:50 AM UTC

HTML:

<!--Toolbar section-->
<ejs-toolbar id="toolbar" class="toggle" (created)='createAndLinkToolbarObjects()'>
<e-items>
<e-item text='Add scrapbook' prefixIcon="e-icons e-circle-add"
(click)="onAddScrap($event)">
</e-item>
<e-item type='Separator'></e-item>

<e-item text='Add category' prefixIcon="e-icons e-add-below"
(click)="onAddCategory($event)" [disabled]="isTbAddCategoryDis"></e-item>
<e-item type='Separator'></e-item>

<e-item text='Edit' prefixIcon="e-edit icon"
[disabled]="isTbEditDis"
(click)="onEdit($event)"></e-item>
<e-item type='Separator'></e-item>

<e-item text='Mail' prefixIcon="e-icons item-email-icon"
[visible]="isMailButtonVisible"></e-item>
<e-item type='Separator' [visible]="isMailButtonVisible"></e-item>

<e-item text='Clear' prefixIcon="e-icons e-table-delete"
[visible]="isClearButtonVisible"
(click)="onClear($event)"
[disabled]="isTbAllowClearDis"></e-item>
<e-item type='Separator' [visible]="isClearButtonVisible"></e-item>

<e-item text='Delete' prefixIcon="e-icons e-circle-remove"
(click)="onDelete($event)" [disabled]="isTbAllowDeleteDis"></e-item>
<e-item type='Separator'></e-item>

<e-item (click)="onPrint($event)" [disabled]="isTbPrintDis"
[visible]="isPrintButtonVisible"
prefixIcon="e-icons e-print" text='Print'></e-item>
<e-item [visible]="isPrintButtonVisible" type='Separator'>Print</e-item>

<e-item text='Scrap book history' prefixIcon="e-icons btn-scrapbook-history"
[visible]="isHistoryButtonVisible"></e-item>
<e-item type='Separator' [visible]="isHistoryButtonVisible"></e-item>

<e-item template='<ejs-checkbox id="visible_chk"></ejs-checkbox>'
[visible]="isShowOwnerChkBoxVisible"></e-item>
</e-items>
</ejs-toolbar>
<!--Toolbar section - END-->

<!--Add Scrapbook modal form section-->
<app-scrapbook-add [ejDialogIsShown]='false'></app-scrapbook-add>
<!--Add Scrapbook modal form section - END-->

<!--Add Category modal form section-->
<app-scrapbook-add-category [ejDialogIsShown]='false'></app-scrapbook-add-category>
<!--Add Category modal form section - END-->

<!--TreeGrid section-->

<!--This is for Scrapbook tab menu page-->
<ejs-treegrid
*ngIf="!isInScrapBookTab"

#scrapBookTreeGrid

[dataSource]='data'
[treeColumnIndex]='1'
[allowRowDragAndDrop]='false'
[rowDropSettings]="{targetID: 'NewsProviderTreeGrid'}"

[selectionSettings]="{type: 'Single'}"
[enableCollapseAll]='false'
[allowPaging]='true'
[pageSettings]="{pageCount: 12}"

(rowSelected)="onRowSelected($event)"
(queryCellInfo)="onQueryCellInfo($event)"
(rowDrop)="onRowDrop($event)"

height="90%"
width="100%"
childMapping='Leafs'

id='destTree'>

<e-columns>
<e-column field='Id' headerText='ID#' width='100' textAlign='Right' isPrimaryKey='true'
[visible]="false"></e-column>
<e-column field='Title' headerText='Title' width='225'></e-column>
</e-columns>

</ejs-treegrid>
<!--This is for Scrapbook tab menu page - END-->

<!--This is for when it is not in scrapbook tab-->
<ejs-treegrid
*ngIf="isInScrapBookTab"

#scrapBookTreeGrid

[dataSource]='data'
[treeColumnIndex]='1'

[allowRowDragAndDrop]='true'
[selectionSettings]="{type: 'Single'}"

[enableCollapseAll]='false'
[allowPaging]='true'
[pageSettings]="{pageCount: 12}"

(rowSelected)="onRowSelected($event)"
(queryCellInfo)="onQueryCellInfo($event)"
(rowDrop)="onRowDrop($event)"

[height]="modalFormHeight"
width="100%"
childMapping='Leafs'>

<e-columns>
<e-column field='Id' headerText='ID#' width='100' textAlign='Right' isPrimaryKey='true'
[visible]="false"></e-column>
<e-column field='Title' headerText='Title' width='225'></e-column>
</e-columns>

</ejs-treegrid>
<!--This is for when it is not in scrapbook tab - END-->

<!--TreeGrid section - END-->

<app-modal-print-document
[modalDialogId]="callModalWithCustomId"
[newsBody]="newsBody"
[newsDate]="newsDate"
[newsSource]="newsSource"
[newsTitle]="newsTitle"
></app-modal-print-document>


Typescrypt:


import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild} from '@angular/core';
import {PageService, RowDDService, TreeGridComponent} from "@syncfusion/ej2-angular-treegrid";
import {CheckBox} from "@syncfusion/ej2-angular-buttons";
import {QueryCellInfoEventArgs} from "@syncfusion/ej2-angular-grids";
import * as sbCart from "../../../common/ng-rx/ScrapBook/sbActions";
import {
ScrapBookTreeType,
TreeCategoryItem,
TreeNewsItem,
TreeScrapBookItem
} from "../../../common/models/ScrapBookTreeItemModels";
import {
AddScrapBookCategoryID,
AddScrapBookWindowID,
EnumModalScrapbookOperationType,
LoggedInUser,
PrintPreviewGeneralModalTemplate,
ScrapBookStore,
ScrapBookTreeGridSelectedItem
} from "../../../common/constants/constants";
import ISbState from "../../../common/models/ISbState";
import {Utils} from "../../../common/utils/utils";
import IScrapModalOperation from "../../../common/models/IScrapModalOperation";
import {
clearScrapBookById,
deleteScrapBookById,
getScrapbookByUser,
updateScrapbookByUser
} from "../../../common/services/scrapbook/scrapbook.service";
import {select, Store} from '@ngrx/store';
import {ScrapBookNewsItemSRDto, ScrapBookSRDto} from "../../../common/models/dto/scrap-book-s-r-dto";
import * as moment from "moment-mini";

@Component({
selector: 'app-scrapbook-tree-grid-scraps',
templateUrl: './scrapbook-tree-grid-scraps.component.html',
styleUrls: ['./scrapbook-tree-grid-scraps.component.scss'],
providers: [RowDDService, PageService]
})
export class ScrapbookTreeGridScrapsComponent implements OnInit, OnDestroy {

@ViewChild('scrapBookTreeGrid') treeGridObj: TreeGridComponent | any;
@Output() onSelectedRow = new EventEmitter<any>();
@Input() isMailButtonVisible: boolean = true;
@Input() isClearButtonVisible: boolean = true;
@Input() isHistoryButtonVisible: boolean = true;
@Input() isShowOwnerChkBoxVisible: boolean = true;
@Input() isInScrapBookTab: boolean = false;
@Input() isPrintButtonVisible: boolean = true;
@Input() modalFormHeight: string = '90%';

checkBox: any;
data: TreeScrapBookItem[] = [];
isTbAddCategoryDis: boolean = true;
isTbAllowClearDis: boolean = true;
isTbAllowDeleteDis: boolean = true;
isTbEditDis: boolean = true;
isTbPrintDis: boolean = true;
treeGridSelectedItem: any;
callModalWithCustomId: string = PrintPreviewGeneralModalTemplate;
newsTitle: string = "";
newsSource: string = "";
newsDate: string = "";
newsBody: string = "";
private dataSub: any;
private dataStoreSub: any;

constructor(private store: Store<ISbState>) {
}

ngOnInit(): void {
this.getScrapbookByUserHelper(); // Fill the store with data !

// Hook the store to the TreeGrid
// @ts-ignore
this.dataStoreSub = this.store.pipe(select('sbCart')).subscribe((data: ISbState) => this.data = data.scrapBookData!);
}

ngOnDestroy(): void {
this.dataSub.unsubscribe();
this.dataStoreSub.unsubscribe();
}

createAndLinkToolbarObjects() {
this.checkBox = new CheckBox({
cssClass: `e-flat e-checkicon`,
name: 'checkBox',
label: 'Show owner',
checked: false
});
this.checkBox.appendTo('#visible_chk');

this.checkBox.element.onclick = (): void => {
const el = this.checkBox.element.checked;
if (el) {

} else {

}
};
}

onAddScrap(args: any) {
const obj = {
operation: EnumModalScrapbookOperationType.AddScrapBook,
item: null
}
Utils.setEnvironmentVar(ScrapBookTreeGridSelectedItem, obj);
(document.getElementById(AddScrapBookWindowID)! as any).ej2_instances[0].show();
}

onAddCategory(args: any) {
const selected = JSON.parse(JSON.parse(Utils.getEnvironmentVar(ScrapBookTreeGridSelectedItem)));
const obj = {operation: EnumModalScrapbookOperationType.AddCategory, item: selected}
Utils.setEnvironmentVar(ScrapBookTreeGridSelectedItem, obj);
(document.getElementById(AddScrapBookCategoryID)! as any).ej2_instances[0].show();
}

dataRefresh(parDataSource: any) {
this.data = JSON.parse(JSON.stringify(parDataSource));
(this.treeGridObj as TreeGridComponent).dataSource = this.data;
this.treeGridObj.refresh();
console.log("Refresh-dataRefresh(parDataSource: any)");
}

onQueryCellInfo(args: QueryCellInfoEventArgs): void {
try {
const {cell, data} = args;

// @ts-ignore
const dataType = data['Type'];
if (dataType === ScrapBookTreeType.ScrapBookDefault || dataType === ScrapBookTreeType.ScrapBook) {
// @ts-ignore
cell.style.fontSize = '14px';
// @ts-ignore
cell.style.fontWeight = 'bold';
// @ts-ignore
cell.style.color = data['Color'];
} else if (dataType === ScrapBookTreeType.Category) {
// @ts-ignore
cell.style.fontSize = '12px';
// @ts-ignore
cell.style.fontWeight = 'bold';
}

} catch (e) {
console.error(e);
}
}

onRowSelected(args: any) {
this.treeGridSelectedItem = args.data;

this.isTbAllowDeleteDis =
!(this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook ||
this.treeGridSelectedItem.Type === ScrapBookTreeType.Category ||
this.treeGridSelectedItem.Type === ScrapBookTreeType.NewsItem);

//Add Category
this.isTbAddCategoryDis = !(this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBookDefault ||
this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook);

//Clear button
this.isTbAllowClearDis = !(this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBookDefault ||
this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook);

//Edit button
this.isTbEditDis = !(this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook ||
this.treeGridSelectedItem.Type === ScrapBookTreeType.Category);

//Print button
this.isTbPrintDis = !(this.treeGridSelectedItem.Type === ScrapBookTreeType.NewsItem);

//Send the selected item to the Category Modal Window through localStorage!
Utils.setEnvironmentVar(ScrapBookTreeGridSelectedItem, JSON.stringify(this.treeGridSelectedItem));

this.onSelectedRow.emit(this.treeGridSelectedItem);

//Set the news information for the print preview
this.newsTitle = this.treeGridSelectedItem?.NewsItemDetails?.title!;
this.newsSource = this.treeGridSelectedItem?.NewsItemDetails?.source!;
this.newsDate = moment(this.treeGridSelectedItem?.NewsItemDetails?.date!).format('DD.MM.YYYY');
this.newsBody = this.treeGridSelectedItem?.NewsItemDetails?.summary!;

console.log("onRowSelected($event: any)", this.treeGridSelectedItem);
}

onRowDrop(args: any) {
try {
// @ts-ignore
const treeGridObj = document.getElementsByClassName('e-treegrid')[0].ej2_instances[0];
const rowCss = args.target?.closest('td')!;
const targetCategory = treeGridObj.getCurrentViewRecords()[args.dropIndex];
const targetCategoryID = targetCategory.Id;
const targetScrapBookId = targetCategory.TreeScrapBookItemId;

// Helps to identify the row where I make the dropOff
const selected: any = args.data[0];
const categoryId = selected.TreeCategoryItemId;
const scrapId = selected.TreeScrapBookItemId;
// ----------------------------------------------------
if (targetCategory.Type === ScrapBookTreeType.Category) {
if (rowCss.classList.contains('e-droptop')) {
rowCss.classList.remove('e-droptop')
args.cancel = 'true'
alert("Dropping disabled. The category needs to fit into a rectangle!")
} else if (rowCss.classList.contains('e-dropbottom')) {
rowCss.classList.remove('e-dropbottom')
args.cancel = 'true'
alert("Dropping disabled. The category needs to fit into a rectangle!")
} else if (targetCategory.Id === categoryId && targetCategory.TreeScrapBookItemId === scrapId) {
args.cancel = 'true'
alert("Dropping disabled for adding item to the same category!")
} else {
const scrapStore = this.data;

const originalScrapId = args.data[0].TreeScrapBookItemId;
const originalCategoryId = args.data[0].TreeCategoryItemId;
const originalScrap = JSON.parse(JSON.stringify(scrapStore.find((x: any) => x.Id === originalScrapId)!));
const originalCategory = originalScrap.Leafs.find((x: any) => x.Id === originalCategoryId)!;

const targetScrapItem = JSON.parse(JSON.stringify(scrapStore.find((x: any) => x.Id === targetScrapBookId)!));
const targetCategoryItem = targetScrapItem.Leafs.find((x: any) => x.Id === targetCategoryID)!;
if (targetCategoryItem.Leafs === undefined ||
targetCategoryItem.Leafs === null ||
targetCategoryItem.Leafs.length === 0) {
targetCategoryItem.Leafs = [];
}

const scrapOriginalEqualsTarget = originalScrap.Id === targetScrapItem.Id;
for (let i in args.data) {
const item: TreeNewsItem = args.data[i] as TreeNewsItem;
const newsId = item.Id;
// check if news already in category if exits we do not add the item in the target category
const scrapTargetItemNews = targetCategoryItem.Leafs.find((x: any) => x.Id === newsId)!;
if (!scrapTargetItemNews) {
const newNewsItem = {
Id: item.Id,
Title: item.Title,
NewsItemDetails: item.NewsItemDetails,
Type: ScrapBookTreeType.NewsItem,
TreeCategoryItemId: targetCategoryID,
TreeScrapBookItemId: targetScrapBookId,
} as TreeNewsItem;
targetCategoryItem.Leafs.push(JSON.parse(JSON.stringify(newNewsItem)));
if (scrapOriginalEqualsTarget) { // check to see if same scrapbook
const targetCategory = targetScrapItem.Leafs.find((x: any) => x.Id === originalCategoryId)!;
const i = targetCategory.Leafs.findIndex((x: any) => x.Id === newsId);
// delete the item from targetCategoryItem.Leafs
targetCategory.Leafs.splice(i, 1);
} else {
//delete item from original category
const i = originalCategory.Leafs.findIndex((x: any) => x.Id === newsId)!;
originalCategory.Leafs.splice(i, 1);
}
}
}
// Now we need to make an update to the database and then refresh the store!
const newOriginalScrap: TreeScrapBookItem = JSON.parse(JSON.stringify(originalScrap)) as TreeScrapBookItem;
const newTargetScrap: TreeScrapBookItem = JSON.parse(JSON.stringify(targetScrapItem)) as TreeScrapBookItem;

const elements: any = document.getElementsByClassName("e-cloneproperties e-draganddrop e-grid e-dragclone e-movecur");
if (elements && elements.length > 0) {
const element = elements[0];
element.style.display = 'none';
debugger
if (window.CustomEvent) {
element.dispatchEvent(new CustomEvent('contextmenu'));
} else if (document.createEvent) {
const ev = document.createEvent('HTMLEvents');
ev.initEvent('contextmenu', true, false);
element.dispatchEvent(ev);
} else { // Internet Explorer
element.fireEvent('oncontextmenu');
}
}

if (scrapOriginalEqualsTarget) {
updateScrapbookByUser(Utils.getScrapbookItemForDB(newTargetScrap)).subscribe((res) => {
if (res) {
this.dataSub = getScrapbookByUser().subscribe((data: TreeScrapBookItem[]) => {
args.cancel = 'true'
Utils.removeEnvironmentVar(ScrapBookStore);
this.store.dispatch(new sbCart.InitializeScrapStore(data));
this.treeGridObj.refresh();
// args.preventDefault();
});
}
});
} else {
updateScrapbookByUser(Utils.getScrapbookItemForDB(newOriginalScrap)).subscribe((res) => {
if (res) {
updateScrapbookByUser(Utils.getScrapbookItemForDB(newTargetScrap)).subscribe((res) => {
if (res) {
this.dataSub = getScrapbookByUser().subscribe((data: TreeScrapBookItem[]) => {
args.cancel = 'true'
Utils.removeEnvironmentVar(ScrapBookStore);
this.store.dispatch(new sbCart.InitializeScrapStore(data));
this.treeGridObj.refresh();
// args.preventDefault();
});
}
});
}
});
}
}
} else {
args.cancel = 'true'
alert("Dropping disabled for anything other than category!")
}
} catch (e) {
console.error(e);
}
// args.cancel = 'true';
}

onDelete(args: any) {
if (this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook) {
deleteScrapBookById(this.treeGridSelectedItem.Id).subscribe((res) => {
if (res) {
this.store.dispatch(new sbCart.RemoveScrapBook(this.treeGridSelectedItem.Id));
}
});
} else if (this.treeGridSelectedItem.Type === ScrapBookTreeType.Category) {
// When we delete a category we actually have to make an update in the DB
// and then take it out from the store!
const scrapId = this.treeGridSelectedItem.TreeScrapBookItemId
const categoryName = this.treeGridSelectedItem.Title;
const scrapBook: TreeScrapBookItem = this.data.find((item: TreeScrapBookItem) => item.Id === scrapId)!;
const categories: string[] = [], news: ScrapBookNewsItemSRDto[] = [];

for (let i in scrapBook.Leafs) {
const categoryItem: TreeCategoryItem = scrapBook.Leafs[i];
// Each scrapbook has many categories - we put them all under same array of strings
// except the one we delete !
if (categoryItem.Title !== categoryName) {
categories.push(categoryItem.Title!);

for (let j in categoryItem.Leafs) {
const newsItem: TreeNewsItem = categoryItem.Leafs[j];
news.push({
category: categoryItem.Title,
scrapbookItemId: newsItem.Id,
title: newsItem.Title,
source: newsItem.NewsItemDetails?.source,
reference: newsItem.NewsItemDetails?.reference,
logo: newsItem.NewsItemDetails?.logo,
summary: newsItem.NewsItemDetails?.summary,
date: newsItem.NewsItemDetails?.date,
} as ScrapBookNewsItemSRDto);
}
}
}

const dto = {
scrapbookId: scrapId,
categories: categories,
scrapbookItems: news,
color: scrapBook.Color,
name: scrapBook.Title,
owner: JSON.parse(Utils.getEnvironmentVar(LoggedInUser))
} as ScrapBookSRDto;

updateScrapbookByUser(dto).subscribe((res) => {
if (res) {
const category: TreeCategoryItem = {
Id: this.treeGridSelectedItem.Id,
Title: this.treeGridSelectedItem.Title,
Type: ScrapBookTreeType.Category,
TreeScrapBookItemId: this.treeGridSelectedItem.TreeScrapBookItemId
} as TreeCategoryItem;
this.store.dispatch(new sbCart.RemoveCategory(category));
}
});
} else if (this.treeGridSelectedItem.Type === ScrapBookTreeType.NewsItem) {
// When we delete a category we actually have to make an update in the DB
// and then take it out from the store!
const scrapId = this.treeGridSelectedItem.TreeScrapBookItemId
const categoryName = this.treeGridSelectedItem.Title;
const scrapBook: TreeScrapBookItem = this.data.find((item: TreeScrapBookItem) => item.Id === scrapId)!;
const categories: string[] = [], news: ScrapBookNewsItemSRDto[] = [];

for (let i in scrapBook.Leafs) {
const categoryItem: TreeCategoryItem = scrapBook.Leafs[i];
categories.push(categoryItem.Title!);

for (let j in categoryItem.Leafs) {
const newsItem: TreeNewsItem = categoryItem.Leafs[j];
// Each category has many news items - we put them all under same array of newsItems
// except the one we delete !
if (newsItem.Id !== this.treeGridSelectedItem.Id) {
news.push({
category: categoryItem.Title,
scrapbookItemId: newsItem.Id,
title: newsItem.Title,
source: newsItem.NewsItemDetails?.source,
reference: newsItem.NewsItemDetails?.reference,
logo: newsItem.NewsItemDetails?.logo,
summary: newsItem.NewsItemDetails?.summary,
date: newsItem.NewsItemDetails?.date,
} as ScrapBookNewsItemSRDto);
}
}
}

const dto = {
scrapbookId: scrapId,
categories: categories,
scrapbookItems: news,
color: scrapBook.Color,
name: scrapBook.Title,
owner: JSON.parse(Utils.getEnvironmentVar(LoggedInUser))
} as ScrapBookSRDto;

debugger
updateScrapbookByUser(dto).subscribe((res) => {
if (res) {
const newsItem: TreeNewsItem = {
Id: this.treeGridSelectedItem.Id,
TreeScrapBookItemId: this.treeGridSelectedItem.TreeScrapBookItemId,
TreeCategoryItemId: this.treeGridSelectedItem.TreeCategoryItemId,
Title: this.treeGridSelectedItem.Title,
Type: ScrapBookTreeType.NewsItem,
NewsItemDetails: this.treeGridSelectedItem.NewsItemDetails
} as TreeNewsItem;
this.store.dispatch(new sbCart.RemoveNewsItem(newsItem));
}
});
}

// this.dataRefresh(this.data);
}

onEdit(args: any) {
let obj = {} as IScrapModalOperation;
if (this.treeGridSelectedItem.Type === ScrapBookTreeType.ScrapBook) {
obj = {
operation: EnumModalScrapbookOperationType.EditScrapBook,
item: this.treeGridSelectedItem
};
Utils.setEnvironmentVar(ScrapBookTreeGridSelectedItem, obj);
(document.getElementById(AddScrapBookWindowID)! as any).ej2_instances[0].show();
} else if (this.treeGridSelectedItem.Type === ScrapBookTreeType.Category) {
obj = {
operation: EnumModalScrapbookOperationType.EditCategory,
item: this.treeGridSelectedItem
};
Utils.setEnvironmentVar(ScrapBookTreeGridSelectedItem, obj);
(document.getElementById(AddScrapBookCategoryID)! as any).ej2_instances[0].show();
}
}

onClear(args: any) {
//Get the selected scrapbook id !
const scrapBookId = this.treeGridSelectedItem.Id;
clearScrapBookById(scrapBookId).subscribe((res) => {
if (res) {
this.store.dispatch(new sbCart.ClearScrapBook(scrapBookId));
}
});
}

onPrint(args: any) {
(document.getElementById(this.callModalWithCustomId)! as any).ej2_instances[0].show();
}

getScrapbookByUserHelper() {
//Get the data for ScrapBook TreeGrid from the server and put it in the store!
this.dataSub = getScrapbookByUser().subscribe((data: TreeScrapBookItem[]) => {
Utils.removeEnvironmentVar(ScrapBookStore);
this.store.dispatch(new sbCart.InitializeScrapStore(data));
});
}
}


AL AlexB October 14, 2022 11:31 AM UTC

I have put a recording of the screen sample in the zip file 


Attachment: screen_recording_c4724f6.zip


FS Farveen Sulthana Thameeztheen Basha Syncfusion Team October 17, 2022 03:34 PM UTC

Hi AlexB,


We have prepared sample based on your code snippet provided but we are unable to replicate the problem at our end. Refer to the sample link:-

https://stackblitz.com/edit/angular-gqu5jt-zyfxny?file=app.component.html


From your code, we suspect that you have handled some customizations in rowDrop event of the TreeGrid which may leads to the reported problem. So please ensure by removing the code on rowDrop event and check the issue occurs still.


Also we need some more additional details to find the exact cause of the issue. Share us the following details.


  1. Why you need to perform the customization on rowDrop event.(Do you want to prevent drop action for specific record). If yes please refer KB https://www.syncfusion.com/kb/11771/how-to-customize-drag-and-drop-operation-of-tree-grid
  2. Share the purpose or detailed scenario of your requirement.
  3. If possible replicate the same in the above sample and revert us back.
  4. Share Stacktrace of Script Error if any occur on console window(by Screenshot/Video demo)


Regards,
Farveen sulthana T



AL AlexB October 22, 2022 08:36 PM UTC

What I'm trying to achieve is this:

When I drag an article(group of articles) on top of a category (it is surrounded by a red square - not on the top line not on the bottom line !) I need to see them in the new category and delete them from the old category!

This behavior is working ... now after all of this I want to post the modifications to the database and if ok I want to update the store (I'm using NgRx) and the store feeds the TreeGrid​ with data.

This behavior is also working but after this step, I'm stuck with the selection on the mouse cursor like in the video and I can not shake it off unless I click outside the TreeGrid or I do a right-click somewhere.

Recap :
Step 1 - check if the category is selected (squared with red)
Step 2 - get the data and post it to the server
Step 3 - if Post ok then update store/TreeGrid
Step 4 - getting stuck with the selection attached on the mouse cursor!

If I only do Step 1, Step 4 disappears but I need to do steps 2 and 3 they are mandatory I can do them in the separate event but I did not notice TreeGrid having an event afterRowDrop finished or something similar.



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team October 25, 2022 11:25 AM UTC

Hi AlexB,


From your provided code example, we suspect that you have used Remote Data. While using RowDragandDrop we need to handle the operations at server end as like provided code.


App.Component.html:-

<ejs-treegrid id='TreeGrid' [dataSource]='data' [allowRowDragAndDrop]='true' height='315' [allowPaging]="true" [pageSettings]='pageSetting' [treeColumnIndex]='1'[selectionSettings]='selectionSettings'  parentIdMapping='ParentValue'

         idMapping='TaskID ' (rowDrop)='rowDrop($event)'  hasChilsMapping='isParent ' >

    <e-columns>

        <e-column field='TaskID' headerText='Task ID' [isPrimaryKey]='true' textAlign='Right' width=90></e-column>

        <e-column field='TaskName' headerText='Task Name' textAlign='Left' width=180></e-column>

 

                .   .     .

  </ejs-treegrid>

 

App.Component.ts:-

 

     rowDrop(args) {

   

        var record = this.treegrid.getCurrentViewRecords()[args.fromIndex][this.idMapping];

        var record2 = this.treegrid.getCurrentViewRecords()[args.dropIndex][this.idMapping];

        var data = args.data[0];

        var position = { dragidMapping: record, dropidMapping: record2, position: args.dropPosition };

         // if you need to update the Row Drag and Drop value at server end you can use ajax post

        $.ajax({

           url: '@Url.Action("MyTestMethod")',

            data: JSON.stringify({ value: data, pos: position }),

            dataType: "json",

            method: 'POST',

           contentType: "application/json; charset=utf-8",

           success: function (data) {

              

           }

      });

    }

Serverside:-

 

public bool MyTestMethod([FromBody]ICRUDModel value)

        {

            if (value.pos.position == "bottomSegment" || value.pos.position == "topSegment")

            {

                //for bottom and top segment drop position. If the dragged record is the only child for a particular record,

                //we need to set parentItem of dragged record to null and isParent of dragged record's parent to false

                if (value.value.ParentValue != null) // if dragged record has parent

                {

                    var childCount = 0;

                    int parent1 = (int)value.value.ParentValue;

                    childCount += FindChildRecords(parent1); // finding the number of child for dragged record's parent

                    if (childCount == 1) // if the dragged record is the only child for a particular record

                    {

                        var i = 0;

                        for (; i < TreeData.tree.Count; i++)

                        {

                            if (TreeData.tree[i].TaskID == parent1)

                            {

                                //set isParent of dragged record's parent to false

                                TreeData.tree[i].isParent = false;

                                break;

                            }

                            if (TreeData.tree[i].TaskID == value.value.TaskID)

                            {

                                //set parentId of dragged record to null

                                TreeData.tree[i].ParentValue = null;

                                break;

                            }

 

 

                        }

                    }

                }

                TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == value.pos.dragidMapping).FirstOrDefault());

                var j = 0;

                for (; j < TreeData.tree.Count; j++)

                {

                    if (TreeData.tree[j].TaskID == value.pos.dropidMapping)

                    {

                        //set drgged records parentId with parentId of

                        //record in dropindex

                        value.value.ParentValue = TreeData.tree[j].ParentValue;

                        break;

                    }

                }

                if (value.pos.position == "bottomSegment")

                {

                    this.Insert(value.value, value.pos.dropidMapping);

                }

                else if (value.pos.position == "topSegment")

                {

                   this.InsertAtTop(value.value, value.pos.dropidMapping);

                }

            }

            else if (value.pos.position == "middleSegment")

            {

                TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == value.pos.dragidMapping).FirstOrDefault());

                value.value.ParentValue = value.pos.dropidMapping;

                FindDropdata(value.pos.dropidMapping);

                this.Insert(value.value, value.pos.dropidMapping);

            }

            return true;

        }


API Link:-

https://ej2.syncfusion.com/documentation/api/treegrid/#rowdrop


Still faced issue, share details such as please confirm whether you are using RemoteData/Local data, Complete code details to proceed further.


Regards,

Farveen sulthana T


Loader.
Live Chat Icon For mobile
Up arrow icon