I wanted to show a menu when clicking the column headers of a DetailsList, similar to how SharePoint does it. Fluent UI 8 does not have any built in support for this, so I had to figure out a way to do it myself.
Here is a sample project showing my solution. When clicking the column headers you get a menu allowing you to sort the list based on that column. Not very existing, but it shows how to dynamically build and position the context menu, and how to handle when the user selects a menu option depending on the column.
Get the full project code on GitHub
Most of the files are just generated boilerplace code. The interesting part is App.tsx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
import React, { useEffect } from 'react'; import './App.css'; import { ContextualMenu, DetailsList, DirectionalHint, IColumn, IContextualMenuItem } from '@fluentui/react'; interface IFruit { [key:string]: string; name: string; color: string; } export const App: React.FunctionComponent = () => { const [menuDomTarget, setMenuDomTarget] = React.useState<HTMLElement | undefined>(undefined); const [menuItems, setMenuItems] = React.useState<IContextualMenuItem[]>([]); const [clickedColumn, setClickedColumn] = React.useState<IColumn | undefined>(undefined); const [listItems, setListItems] = React.useState<IFruit[]>([ { name: "Strawberry", color: "Red" }, { name: "Pear", color: "Green" }, { name: "Apple", color: "Red" }, { name: "Banana", color: "Yellow" }, { name: "Grapes", color: "Green" }, { name: "Pineapple", color: "Yellow" }, { name: "Watermelon", color: "Green" }, ]); const onColumnClick = (ev?: React.MouseEvent<HTMLElement>, column?: IColumn): void => { setMenuDomTarget(ev?.currentTarget); setClickedColumn(column); }; const [columns, setColumns] = React.useState<IColumn[]>([ { key: 'name', name: "Name", fieldName: 'name', minWidth: 100, isRowHeader: true }, { key: 'color', name: "Color", fieldName: 'color', minWidth: 100, } ]); const sortItems = (columnKey: string, sortDescending: boolean): void => { // Update columns to show sort order icon const newColumns: IColumn[] = columns.slice(); const currColumn: IColumn = newColumns.filter(currCol => columnKey === currCol.key)[0]; newColumns.forEach((newCol: IColumn) => { if (newCol === currColumn) { currColumn.isSortedDescending = sortDescending; currColumn.isSorted = true; } else { newCol.isSorted = false; newCol.isSortedDescending = true; } }); setColumns(newColumns); // Sort the items accordingly const newItems = [...listItems]; newItems.sort((a: IFruit, b: IFruit) => { if(sortDescending) return b[columnKey].localeCompare(a[columnKey]) else return a[columnKey].localeCompare(b[columnKey]) }); setListItems(newItems); }; useEffect(() => { if(clickedColumn) { // Dynamically generate the menu items based on the clicked column. const items: IContextualMenuItem[] = [ { key: "sortAsc", text: "A to Z", iconProps: { iconName: "Ascending"}, onClick: () => {sortItems(clickedColumn.key, false)}, }, { key: "sortDesc", text: "Z to A", iconProps: { iconName: "Descending"}, onClick: () => {sortItems(clickedColumn.key, true)}, } ]; setMenuItems(items); } }, [clickedColumn, sortItems]); return ( <div className="container"> <DetailsList items={listItems} columns={columns} isHeaderVisible={true} onColumnHeaderClick={onColumnClick} className="details-list" /> {menuDomTarget !== undefined && <ContextualMenu items={menuItems} hidden={menuDomTarget === undefined} target={menuDomTarget} onItemClick={() => setMenuDomTarget(undefined)} onDismiss={() => setMenuDomTarget(undefined)} directionalHint={DirectionalHint.bottomLeftEdge} /> } </div> ); }; |
IN SHORT= provide an update to flash renamer
hello I have been using many renaming softwares earlier, but once I started using the context menu of flash renamer, there is no competition out there in windows. I can just click multiple files and do the renaming as desired Through context menu , but there are some bugs and features that are missing in flash renamer.
1} I cannot select and rename multiple folders through context menu of Flash Renamer.
2} the flash renamer does not truncate aka restrict aka trim the length name of the file to 75 characters as I want. {Like suppose there is a file with name length more than 75 characters, I want to limit the file name length to 75 characters(including suffix and prefix) from the context menu.
original NAME 1= 1st23456789——–75th—100th (NUMBER = CHARACTER LENGTH)
my desired name= (prefix)001———-XYZ(suffix)= total character length to remain 75 as i desire.
3) better ui.