i am using ng2 dragula's COLUMNS feature of dragging and dropping and in that when the scroller comes, i am unable to scroll up/down while drag/drop.
import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { MenuAPI } from '@api/menu.api';
import { ViewAPI } from '@api/view.api';
import {
AlertBoxRespone,
CommonResp,
EDITVIEWRES,
Menu,
SCREENTITLE,
StatusCodeMessageAPIResponse,
VIEWLIST
} from '@interface';
import { ALERTBOXOBJ, AlertBoxService, AlertID, AlertMessages } from '@service/alert-box.service';
import { ApiHandleService, LOADERSTATE, TOASTRTYPE } from '@service/api-handle.service';
import { CommonMethodsService } from '@service/common-methods.service';
import { ConstantService } from '@service/constant.service';
import { LoaderID, Routes, ToastrMessage } from '@service/string-constant';
import { DragulaService } from 'ng2-dragula';
import { Subscription, firstValueFrom, take } from 'rxjs';
@Component({
selector: 'app-dashboard-beta',
templateUrl: './dashboard-beta.component.html',
styleUrls: ['./dashboard-beta.component.scss']
})
export class DashboardBetaComponent implements OnInit, OnDestroy {
screenTitle: SCREENTITLE = {
header: 'Dashboard Management',
desc: ''
};
loaderId = LoaderID;
Routes = Routes;
subs = new Subscription();
isCollapsed = false;
flag: {
editedViewName: string;
editMode: boolean;
} = {
editedViewName: '',
editMode: false
};
constructor(
private dragulaService: DragulaService,
private _menuAPI: MenuAPI,
private _apiHandle: ApiHandleService,
public _constant: ConstantService,
private _viewAPI: ViewAPI,
private _commonMethod: CommonMethodsService,
private _alertBox: AlertBoxService,
public DomSanitizationService: DomSanitizer
) {}
ngOnInit(): void {
this.dragulaService.createGroup('COLUMNS', {
direction: 'horizontal',
moves: (el, container, handle): any => {
if (handle?.classList.contains('common-handle')) {
return false;
}
return true;
}
});
this.subs.add(
this.dragulaService.drop('COLUMNS').subscribe((value) => {
console.log('dashboards are moving', value);
})
);
let sourceDashboard: string; // Store the source dashboard
let targetDashboard: string; // Store the target dashboard
this.subs.add(
this.dragulaService.drag('ITEMS').subscribe(({ el, source }) => {
sourceDashboard = this.getDashboardFromElement(el.parentElement as HTMLElement);
})
);
this.dragulaService.drop('ITEMS').subscribe((value) => {
targetDashboard = this.getDashboardFromElement(value.el.parentElement as HTMLElement);
if (sourceDashboard === targetDashboard) {
console.log('views are moving within a dashboard');
} else {
console.log('views are moving across the dashboards');
}
});
this.dragulaService.drag('ITEMS').subscribe(({ el }) => {
el.classList.add('dragging');
});
this.dragulaService.dragend('ITEMS').subscribe(({ el }) => {
el.classList.remove('dragging');
console.log("vlvll");
});
this.getMenuList();
}
getDashboardFromElement(element: HTMLElement): string {
const dashboardElement = element.closest('.container-1');
if (dashboardElement) {
const dashboardIndex = Array.from(
dashboardElement.parentElement?.children || []
).indexOf(dashboardElement);
return this._constant.menuList[dashboardIndex]?.group_menu_id || '';
}
return '';
}
async getMenuList(): Promise<void> {
let arrayResponse: Menu[] = [];
try {
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.START
);
const res = await firstValueFrom(
this._menuAPI.menu({
menus: '-1',
search_text: '-1'
})
);
this._apiHandle.showStopLoader(LoaderID.DASHBOARD_MANAGEMENT_CENTRIC, LOADERSTATE.STOP);
if (res?.status_code === 1) {
arrayResponse = res.data.map((item) => {
const viewDetails = item.view_detail.map((view) => ({
...view,
editView: false
}));
return { ...item, view_detail: viewDetails };
});
// O(n*m) // can be improved if backend can send an extra key
} else {
throw new Error(res?.msg || ToastrMessage.FAILED_FETCHING_DASHBOARD_LIST);
}
console.log(arrayResponse);
this._constant.menuList = arrayResponse;
} catch (err) {
this._constant.menuList = [];
this._apiHandle.APIErrorHandling(
err as HttpErrorResponse,
ToastrMessage.FAILED_FETCHING_DASHBOARD_LIST,
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC
);
}
}
ngOnDestroy(): void {
this.dragulaService.destroy('COLUMNS');
this.dragulaService.destroy('ITEMS');
this.subs.unsubscribe();
}
clearFlags(view: VIEWLIST): void {
this.flag.editedViewName = '';
view.editView = false;
}
async editView(view: VIEWLIST, editView: boolean = false): Promise<void> {
if (!view.view_name.trim() || (editView && !this.flag.editedViewName.trim())) {
this._apiHandle.showNotification(ToastrMessage.VIEW_NAME_MISSING, TOASTRTYPE.WARNING);
return;
}
const params = {
view_name: this.flag.editedViewName || view.view_name.trim(),
group_view_id: view.group_view_id,
is_favourite: !view.is_favourite
};
this._apiHandle.showStopLoader(LoaderID.DASHBOARD_MANAGEMENT_CENTRIC, LOADERSTATE.START);
try {
const res: EDITVIEWRES = await firstValueFrom(this._viewAPI.editView(params));
this._apiHandle.showStopLoader(LoaderID.DASHBOARD_MANAGEMENT_CENTRIC, LOADERSTATE.STOP);
if (res.status_code === 1) {
view.is_favourite = !view.is_favourite;
if (!editView) {
view.is_favourite
? this._apiHandle.showNotification(
ToastrMessage.VIEW_FAVOURITE_ADDED,
TOASTRTYPE.SUCCESS
)
: this._apiHandle.showNotification(
ToastrMessage.VIEW_FAVOURITE_REMOVED,
TOASTRTYPE.SUCCESS
);
} else {
view.view_name = this.flag.editedViewName;
}
} else {
this._apiHandle.APIErrorHandling(
new HttpErrorResponse({
error: { msg: res?.msg || ToastrMessage.VIEW_EDIT_FAIL }
}),
ToastrMessage.VIEW_EDIT_FAIL,
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC
);
}
this.clearFlags(view);
} catch (err) {
this.clearFlags(view);
this._apiHandle.APIErrorHandling(
err as HttpErrorResponse,
ToastrMessage.VIEW_EDIT_FAIL,
LoaderID.VIEW_CRUD
);
}
}
deleteView(view: VIEWLIST, dashboardIndex: number, viewIndex: number): void {
this._alertBox.openAlert({
...ALERTBOXOBJ,
message: AlertMessages.VIEW_DELETE(view.view_name),
ID: AlertID['VIEW_DELETE']
});
this._alertBox.onClose
.pipe(take(1))
.subscribe(async (alertResponse: AlertBoxRespone): Promise<void> => {
if (alertResponse.id !== AlertID['VIEW_DELETE'] || !alertResponse.response) {
return;
}
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.START
);
try {
const res: StatusCodeMessageAPIResponse = await firstValueFrom(
this._viewAPI.deleteView({ group_view_id: view.group_view_id })
);
if (res.status_code === 1) {
this._constant.menuList[dashboardIndex].view_detail.splice(viewIndex, 1);
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.STOP
);
this._apiHandle.showNotification(
res.msg || ToastrMessage.VIEW_DELETE_SUCCESS,
TOASTRTYPE.SUCCESS
);
} else {
throw new Error(res?.msg || ToastrMessage.VIEW_DELETE_FAIL);
}
} catch (err) {
this._apiHandle.APIErrorHandling(
err as HttpErrorResponse,
ToastrMessage.VIEW_DELETE_FAIL,
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC
);
}
});
}
deleteDashboard(menu: Menu): void {
this._alertBox.openAlert({
...ALERTBOXOBJ,
message: AlertMessages.MENU_DELETE(menu.is_favourite),
ID: AlertID['MENU_DELETE']
});
this._alertBox.onClose
.pipe(take(1))
.subscribe(async (alertResponse: AlertBoxRespone): Promise<void> => {
if (alertResponse.id !== AlertID['MENU_DELETE'] || !alertResponse.response) {
return;
}
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.START
);
try {
const res: CommonResp = await firstValueFrom(
this._menuAPI.deleteMenu(menu.group_menu_id)
);
if (res?.status_code !== 1) {
this._apiHandle.showNotification(
res?.msg || ToastrMessage.MENU_DELETE_SUCCESS,
TOASTRTYPE.SUCCESS
);
this._constant.menuUpdate.emit();
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.STOP
);
} else {
throw new Error(res?.msg || ToastrMessage.MENU_DELETE_FAIL);
}
} catch (err) {
this._apiHandle.APIErrorHandling(
err as HttpErrorResponse,
ToastrMessage.MENU_DELETE_FAIL,
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC
);
}
});
}
async toggleDashboardFav(menu: Menu, menuIndex: number): Promise<void> {
if (menu.is_favourite) {
return;
}
this._apiHandle.showStopLoader(LoaderID.DASHBOARD_MANAGEMENT_CENTRIC, LOADERSTATE.START);
try {
const res: CommonResp = await firstValueFrom(
this._menuAPI.editMenu({ ...menu, is_favourite: true })
);
if (res?.status_code === 1) {
this._apiHandle.showNotification(
res?.msg || ToastrMessage.SET_MENU_LANDING_SUCCESS,
TOASTRTYPE.SUCCESS
);
menu.is_favourite = true;
this._constant.menuList.forEach((field, index) => {
if (index !== menuIndex) {
this._constant.menuList[index].is_favourite = false;
}
});
this._apiHandle.showStopLoader(
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC,
LOADERSTATE.STOP
);
} else {
throw new Error(res?.msg || ToastrMessage.SET_MENU_LANDING_FAIL);
}
} catch (err) {
this._apiHandle.APIErrorHandling(
err as HttpErrorResponse,
ToastrMessage.SET_MENU_LANDING_FAIL,
LoaderID.DASHBOARD_MANAGEMENT_CENTRIC
);
}
}
scrollTo():void{
console.log("scroll");
}
}
<div class="create-manage-form">
<div class="header pb-0">
{{ screenTitle.header }}
</div>
<div
class="wrapper mb-0 pb-0 mt-3"
dragula="COLUMNS"
[(dragulaModel)]="_constant.menuList">
<div
class="container container-1 scroll-custom"
*ngFor="let group of _constant.menuList; index as dashboardIndex">
<div class="flex-row-custom justify-content-between ps-0 pb-2">
<div class="d-flex flex-column basis pe-2 pt-custom">
<i
[ngClass]="{
'fa-toggle-on': group.is_favourite,
'fa-toggle-off': !group.is_favourite
}"
class="fa-icon fa-solid max-custom-width"
(click)="toggleDashboardFav(group, dashboardIndex)"></i>
<span class="group-handle">{{ group.menu_name }}</span>
<span class="text-ellipsis">Owner:- Bharat Bhashan</span>
</div>
<div class="flex-column-custom custom-padding-right pt-0">
<i
class="fa-solid fa-pen-to-square fa-icon"
[routerLink]="[Routes.MENU_MANAGEMENT + '/action/edit']"
[queryParams]="{ id: group.group_menu_id }"></i>
<i
class="fa-solid fa-trash fa-icon"
(click)="deleteDashboard(group)"></i>
<i
class="fa-solid fa-share-nodes fa-icon"
[routerLink]="[Routes.MENU_MANAGEMENT + '/action/share']"
[queryParams]="{ id: group.group_menu_id, name: group.menu_name }"></i>
</div>
</div>
<div
class="container container-2"
dragula="ITEMS"
[(dragulaModel)]="group.view_detail" (mousedown)
="scrollTo()">
<ng-container *ngIf="group.view_detail.length === 0">
<div class="p-4 text-center paxviz-disabled">No Views Found!</div>
</ng-container>
<div
class="container container-3 scroll-custom common-handle"
[ngClass]="{ 'height-80': !group.view_detail.length }"
*ngFor="let item of group.view_detail; index as viewIndex">
<div class="flex-row-custom justify-content-between p-0 common-handle custom-one" >
<div class="d-flex flex-column basis ps-0 common-handle" >
<div class="flex-row-custom gap-1 ps-0 common-handle">
<ng-container *ngIf="!item.editView; else EDITVIEW">
<i
class="fa-solid fa-star fa-icon"
*ngIf="item.is_favourite"></i>
<i
class="fa-regular fa-star fa-icon"
*ngIf="!item.is_favourite"></i>
<span class="text-ellipsis common-handle">{{ item.view_name }}</span>
</ng-container>
</div>
<span class="text-ellipsis common-handle">Owner:- Vishal</span>
</div>
<div class="container-4 flex-column-custom pe-0">
<i
*ngIf="!item.editView"
class="fa-solid fa-pen-to-square fa-icon"
(click)="item.editView = !item.editView"></i>
<i
*ngIf="item.editView"
class="fa-icon fa-solid fa-check"
(click)="editView(item, true)">
</i>
<i
class="fa-solid fa-trash fa-icon"
(click)="deleteView(item, dashboardIndex, viewIndex)"></i>
<i
class="fa-solid fa-star fa-icon"
*ngIf="item.is_favourite"
(click)="editView(item)"></i>
<i
class="fa-regular fa-star fa-icon"
*ngIf="!item.is_favourite"
(click)="editView(item)"></i>
</div>
</div>
<ng-template #EDITVIEW>
<div
class="view-name-input input-with-icon w-100 ps-0"
*ngIf="item.editView">
<input
autofocus
autocomplete="off"
[id]="item.group_view_id + 'edit-name'"
class="paxviz-input bg-white ps-2 pe-4 w-100"
[placeholder]="item.view_name || 'Name...'"
[(ngModel)]="flag.editedViewName"
(keyup.enter)="editView(item, true)" />
<i
class="fa-icon-red fa-regular fa-circle-xmark"
(click)="clearFlags(item)"></i>
</div>
</ng-template>
</div>
</div>
</div>
<ngx-ui-loader [loaderId]="loaderId.DASHBOARD_MANAGEMENT_CENTRIC"></ngx-ui-loader>
</div>
</div>
When the scroller comes and i try to drag the element from the top and try to drop it at the end, im unable to do so because im unable to scroll till down while dragging. Kindly help as soon as possible.
i am trying to scroll up and down while dragging but unable to do so.
i am using ng2 dragula's COLUMNS feature of dragging and dropping and in that when the scroller comes, i am unable to scroll up/down while drag/drop.
.ts file:-
When the scroller comes and i try to drag the element from the top and try to drop it at the end, im unable to do so because im unable to scroll till down while dragging. Kindly help as soon as possible.
i am trying to scroll up and down while dragging but unable to do so.