I’m not able to display complete context menu without making use of a method which is implemented with the help of extensions.
I am displaying context menu by making use of @contextmenu in v-data-table as below,
<v-data-table
v-if="makeFilelist"
:headers="makeHeaders()"
:items="makeFilelist"
:items-per-page="10"
:key="getCurrentPathNum"
:single-select="false"
item-key="id"
show-select
:items-per-page-options="items_per_page"
v-model="selectedItems"
@click:row="OnClick"
@update:options="paginate"
mobile-breakpoint="0"
items-per-page-text="表示件数:"
class="elevation-0"
:footer-props="footerProps"
@click.right="rightClicked"
@contextmenu="show"
@pagination="paginate"
:loading="isGettingFileLists"
loading-text=""
return-object
>
I have written implementation of v-menu as below,
<v-menu
v-if="showMenu"
v-model="showMenu"
location="bottom"
:style="{ left: `${x}px`, top: `${y}px`, position: 'absolute' }"
offset-y
:close-on-content-click="false"
>
<v-list id="contextList">
<!-- Ripple is added to fix when last selected context menu item is focused when context menu selected for next time! -->
<v-list-item
v-for="(item, index) in makeItems"
:key="index"
:value="item"
@click="onMenuClick(item)"
@keydown.tab.stop
:ripple="showMenu ? true : false"
>
<!-- removed v-list-item-icon to fix: Failed to resolve component: v-list-item-icon
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. -->
<!-- <v-list-item-icon> -->
<!-- modified width for displaying context menu images in correct size -->
<v-img
class="downloadIcon"
:src="item.icon"
contain
width="32px"
></v-img>
<!-- </v-list-item-icon> -->
<v-list-item-title
style="position: relative; bottom: 30px; margin-left: 60px"
>{{ item.title }}</v-list-item-title
>
</v-list-item>
</v-list>
</v-menu>
And the implementation for displaying context menu by using extension method as below,
function show(e: any) {
let fileName;
const pdfOrImageExtensions = ["jpg", "jpeg", "pdf", "png", "gif"];
const allowedTagNames = ["TD", "TR", "IMG", "SPAN"];
if (allowedTagNames.includes(e.target.tagName)) {
let tokenIndex = 5;
let typeIndex = 6;
const itemNameIndex = 2;
let targetData: HTMLDivElement;
if (width.value <= 600) {
typeIndex = 4;
tokenIndex = 3;
}
e.preventDefault();
if (e.currentTarget.tagName === "TR") {
targetData = e.currentTarget as HTMLDivElement;
// used to get full file name with extension
// fileName = e.currentTarget.children[2].children[0].textContent;
} else {
//get tr element from currenttarget by using parent node
targetData = e.target.closest("tr");
// // used to get full file name with extension
// fileName = targetData.children[2].children[0].textContent;
}
// used to get full file name with extension
fileName = targetData.children[2].children[0].textContent;
// used for extracting extension from received file name
const extension: any = fileName?.split(".").pop()?.toLowerCase();
// for checking if file right clicked on is folder or not
const isFolder = fileName?.includes(".");
x.value = e.clientX;
// Added to correct y axis to show menu list properly
y.value = e.clientY + window.scrollY;
// added to display the context menu fully
// conditions modified to display context menu fully
if (pdfOrImageExtensions.includes(extension)) {
// context menu display for pdf and image files
if (y.value + 400 > window.innerHeight + window.scrollY) {
//400 is the height of the context menu to be displayed that needs to be reduced to displayed fully
y.value = window.innerHeight - 400 + window.scrollY;
}
} else if (!isFolder) {
// context menu display added for folders
if (y.value + 250 > window.innerHeight + window.scrollY) {
// 270 is the height of the context menu to be displayed that needs to be reduced to displayed fully
y.value = window.innerHeight - 270 + window.scrollY;
}
} else {
// context menu display added for other files
if (y.value + 300 > window.innerHeight + window.scrollY) {
// 330 is the height of the context menu to be displayed that needs to be reduced to displayed fully
y.value = window.innerHeight - 330 + window.scrollY;
}
}
//added for displaying the context menu in left side.
if (is3DotsClicked.value && !isMobileDevice) {
// modified to fix #7183 (Folder/File Context menu is not displayed properly)
x.value = x.value - 200;
}
// added for positioning context menu in correct position
if (x.value + 200 > window.innerWidth) {
x.value = x.value - 200;
} else if (x.value - 240 < 0) {
x.value = x.value - 20;
}
const currentitemInfo = (index: number) => {
if (targetData.children[index]?.textContent != null) {
currentItemInfo.value = targetData.children[index]
.textContent as string;
}
};
targetData.children[typeIndex]?.textContent === "folder"
? currentitemInfo(itemNameIndex)
: currentitemInfo(tokenIndex);
console.log("token=" + targetData.children[tokenIndex]?.textContent);
showMenu.value = false;
nextTick(() => {
showMenu.value = true;
});
}
}
The context menu is written like:
-> when displaying for folder, 4 options need to be displayed.
-> when displaying for pdf and image files, 6 options need to be displayed.
-> and for any other files, 5 options need to be displayed.
I have tried by making use of :target=”[x,y]” prop in v-menu for displaying, this will display correctly but when I scroll the screen and then try to display, then menu is not displayed in correct position. And the context menu is scrolling along with the scroll. That is the reason I have tried to fix by making use of extensions.
I am finding an alternative (other than extension method that is used) for fixing the issue.