I have a requirement to add custom data attributes to the Fluent UI dropdown.
In javascript/html I could add them like this.
option data-passign="true" data-minpt="3" data-maxpt="6" value="7">Data Quality</option
Can someone help me achieve this in Fluent UI + React?
In FluentUI/React, it's much easier than that, no need for data- attributes, you can just add your custom data directly to the options list (and get it back in the event handlers, or as the selected value if you are using "controlled" scenario). Means, if you don't have a specific requirement to store additional item data in the HTML data attributes for "something else" (like ui-automation tool), then you could go with something like this (note the data property):
const YourComponent = (props) => {
const options = [
{ key: '7',
text: 'Data Quality',
data: { passign: true, minpt: 3, maxpt: 7 }
},
{ key: '42',
text: 'Weather Quality',
data: { passign: true, minpt: 100500, maxpt: 42 }
},
];
const onChange = (evt, item) => {
const itemData = item.data;
console.log(item.key, item.text, itemData);
};
return (
<Dropdown
label="Select something"
options={options}
defaultSelectedKey='7'
onChange={onChange}
/>
);
}
If you want a "controlled" control instead (this one is "uncontrolled"), check out the sample page for the Dropdown:
https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown
Related
I am using MUI DataGrid to display a few datasets on the same page and I would like to enable server side sorting, so that when the user sorts, I would also pass in a string to the handler so I can use it to re-fetch data.
<DataGrid
rows={rows}
columns={columns}
sortingMode="server"
sortModel={sortModel}
onSortModelChange={(model) => sortHandler(model)}
/>
...
const sortHandler = (model: GridSortModel) => {
console.table(model);
if (JSON.stringify(model) !== JSON.stringify(sortModel)) {
setSortModel(model);
}
};
The model in the example above will only expose field and sort (see below), but I need at least one more key in that object:
{
"field": "field1",
"sort": "asc"
}
How can I pass extra data to sortHandler, so I can then re fetch the data? Below are the options needed for the API call.
const options = {
...
nestedObj: {
...
},
obj1: {
name: DYNAMIC_VALUE1,
order: DYNAMIC_VALUE2,
rank: DYNAMIC_VALUE3,
},
obj2: {
name: DYNAMIC_VALUE1,
order: DYNAMIC_VALUE2,
rank: DYNAMIC_VALUE3,
},
};
Or is there a better approach? Using field is not enough.
I am attempting to use react-semantic-redux-form SelectField with the multiple options so a user can select multiple options and if there is one already set then this should show as checked.
I am also using redux-form with semantic0ui-react.
I am getting an error attempting to include multiple selections.
My include statement is:
import { SelectField } from "react-semantic-redux-form";
My state is:
state = {
relationships: ["some entry"],
relationshipOptions: [],
};
The element code is:
<Grid.Column>
<Field
component={SelectField}
name="relationships"
label="Your Relationships"
options={relationshipOptions}
multiple
placeholder="Select to add a relationship"
/>
I get the error as below
Dropdown `value` must be an array when `multiple` is set. Received type: `[object String]`.
in Dropdown
The way you have relationshipOptions is wrong, it is supposed array of objects,
const relationshipOptions = [
{ key: "single", value: "single", text: "single" },
{ key: "married", value: "married", text: "married" }
];
Here is the working example, Code Sandbox
Also if you have single, married in array. You can do something like this,
let relationshipOptions = ["single", "married"].map((x) => {
return ({
key: x,
value: x,
text: x
});
});
I am using Fluent UI DetailsList. My table looks like below:
I need filters below every column (text or drop-down) as shown below:
Please let me know if this is possible? Or maybe a way to display custom header (using html) ?
This actually turned out to be easier than I thought it'd be...
If you're ok with clicking the column header to reveal the choices (vs having the dropdown directly under the title) then this can be achieved using the ContextualMenu component in conjunction with DetailsList. I got it working by tweaking from the variable row height example in the official docs: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/variablerowheights.
Add a ContextualMenu underneath your DetailsList:
<DetailsList
items={items}
columns={columns}
/>
{this.state.contextualMenuProps && <ContextualMenu {...this.state.contextualMenuProps} />}
Inside your column definition, set the hasDropdown action so the user gets a UI indicator that they can/should click the header, and call a contextMenu method (note I'm using onColumnContextMenu as well as onColumnClick so it doesn't matter if they left or right click the header:
{
key: 'dept',
name: 'Department',
fieldName: 'dept',
minWidth: 125,
maxWidth: 200,
onColumnContextMenu: (column, ev) => {
this.onColumnContextMenu(column, ev);
},
onColumnClick: (ev, column) => {
this.onColumnContextMenu(column, ev);
},
columnActionsMode: ColumnActionsMode.hasDropdown,
}
When the onColumnContextMenu method gets invoked, we need to build the context menu properties that will get consumed by the ContextualMenu component. Note the dismissal method as well, which clears out the state so the menu is hidden.
private onContextualMenuDismissed = (): void => {
this.setState({
contextualMenuProps: undefined,
});
}
private onColumnContextMenu = (column: IColumn, ev: React.MouseEvent<HTMLElement>): void => {
if (column.columnActionsMode !== ColumnActionsMode.disabled) {
this.setState({
contextualMenuProps: this.getContextualMenuProps(ev, column),
});
}
};
Finally, inside of getContextualMenuProps you need to determine what the options should be for the user to click. In this example, I'm simply giving sort options (you'll need to add an onClick handler to actually do something when the user clicks the item), but I'll use the column to determine what those items should actually be and paint the filters into the items collection so the user can select one to filter.
private getContextualMenuProps = (ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps => {
const items: IContextualMenuItem[] = [
{
key: 'aToZ',
name: 'A to Z',
iconProps: { iconName: 'SortUp' },
canCheck: true,
checked: column.isSorted && !column.isSortedDescending,
},
{
key: 'zToA',
name: 'Z to A',
iconProps: { iconName: 'SortDown' },
canCheck: true,
checked: column.isSorted && column.isSortedDescending,
}
];
return {
items: items,
target: ev.currentTarget as HTMLElement,
directionalHint: DirectionalHint.bottomLeftEdge,
gapSpace: 10,
isBeakVisible: true,
onDismiss: this.onContextualMenuDismissed,
}
}
Note the target on the ContextualMenuProps object, which is what tells the ContextualMenu where to lock itself onto (in this case, the column header that you clicked to instantiate the menu.
Detail list filter for each column without context menu -
https://codesandbox.io/s/rajesh-patil74-jzuiy?file=/src/DetailsList.CustomColumns.Example.tsx
For instance - Providing filter in text field associated with each column will apply filter on color column.
I was trying to implement a custom DropDown filter in ag grid using React.
The link I followed is link
I was able to create the filter, however the filter doesnot appear by default. As a user, we need to click the 3 arrow icon next to the column header and then the filter appears.
Is there a way to display the custom filter dropDown by default?
I hope Floating filters can help you here.
Check this example in ag-grid documentation
filter: "agNumberColumnFilter",
floatingFilterComponent: "sliderFloatingFilter",
floatingFilterComponentParams: {
maxValue: 5,
suppressFilterButton: true
},
The example shows sliderFloatingFilter, to make it a dropdown filter, I think you need to create custom component for it.
Have a look at how ag-grid team has made TextFloatingFilterComp, DateFloatingFilterComp, NumberFloatingFilterComp etc. on GitHub code
Hope this helps.
I achieved dropdown/enum filter using this column configuration. I my case, I was trying to add a boolean filter.
Here is complete example
https://codesandbox.io/s/ag-grid-react-enum-filter-q4er8?file=/src/App.js:1572-1599
const getEnumColumnParams = (enumMap) => {
return {
cellRenderer: (params) => {
if (!params.data) return "";
const { value } = params;
return enumMap[value];
},
filterParams: {
buttons: ['reset', 'apply'],
closeOnApply: true,
filterOptions: [
"empty",
...Object.keys(enumMap).map(key => {
return {
displayKey: key,
displayName: enumMap[key],
test: function (filterValue, cellValue) {
return cellValue === true;
},
hideFilterInput: true,
};
})
],
suppressAndOrCondition: true,
},
};
};
const boolEnum = {
true: 'Yes',
false: 'No'
};
const colorEnum = {
'#ff00000': 'Red',
'#00ff00': 'Green',
'#0000ff': 'Blue',
};
const columnDefs = [
{
field: 'available',
...getEnumColumnParams(boolEnum),
},
{
field: 'color',
...getEnumColumnParams(colorEnum),
}
];
Or you can create column types and assign type: 'boolColumn' etc in column definition like I did in above codesandbox example
I would like to call a custom function in "onFilter" property given by ant design on columns. I can go for the custom filter dropdown as an option but I would like to use the default filter option given by ant design. i.e
{
title: 'Address',
dataIndex: 'address',
key: 'address',
filters: [{
text: 'London',
value: 'London',
}, {
text: 'New York',
value: 'New York',
}],
onFilter: (value, record) => record.address.indexOf(value) === 0,
}
But the only thing I need to change here is a custom function (that will trigger the api call and set the new data in the redux state so the component will re render it self) something like
{
...
onFilter: (value, record) => this.getFilteredData(value),
}
But when I do this I get this error which does make sense too.
Warning: setState(…): Cannot update during an existing state
transition
So kindly guide me on how to do that as I am new to react and ant design both.
Dispatching an action inside onFilter is probably not a good idea because it will be called a couple of times on each filter change
But you can edit your reducer to set filterLoading to true when this action getFilteredData is called and the new onFilter can be like this
...
onFilter: (value) => {
if(! this.props.filterLoading) {
this.getFilteredData(value);
}
return true;
}
A couple of things to consider
You have to pass filterLoading to the component
Don't forget to set filterLoading to false on GET_FILTERED_DATA_SUCCESS action is called
Hope this helps