React Material UI SelectField menu items not appearing - reactjs

Using Material-UI 0.15.1, React 15.2.0
When I click on the SelectField dropdown I get an empty dropdown appearing with out the menu choices appearing. When I use hardcoded MenuItems in the SelectField I see the full menu without issue.
This does not appear to be an injectTapEventPlugin as I am importing it and calling it. My code is below:
render() {
var divStyle = {
fontSize: 16
};
var mymenuItems = [
{ payload: '1', text: 'one' },
{ payload: '2', text: 'two' },
{ payload: '3', text: 'three' },
{ payload: '4', text: 'four' },
{ payload: '5', text: 'five' },
];
return (
<div style={divStyle}>
<SelectField
value={this.state.selected}
onChange={this._onSelect}
floatingLabelText="Product"
menuItems={mymenuItems}>
</SelectField>
</div>
)
}
I am also getting a
Warning: Unknown props onItemTouchTap, disableAutoFocus,
onEscKeyDown on tag. Remove these props from the element
in the console when I click on the SelectField but I saw others had similar issues due to new React version it and it appears people think it should not affect my code (though it is very annoying)

Not sure why you are using menuItems, this property is from old material-ui versions.
But its simple to fix - based on your code you can just map through the array and return MenuItem elements..
Example:
<SelectField
value={this.state.selected}
onChange={this._onSelect}
floatingLabelText="Product">
{mymenuItems.map(x => <MenuItem key={x.payload} value={x.payload} primaryText={x.text} />)}
</SelectField>
I'd suggest you to check the examples on the material-ui docs
http://www.material-ui.com/#/components/select-field

Try putting this in your build:
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
Make sure that function is ran before you render anything to page.
Reference: https://github.com/callemall/material-ui/issues/1011

Related

Fluent-UI's dropdown and combobox both not working

I have a React app with Fluent-UI 8 set up using npm install #fluentui/react according to the documents from Microsoft.
When I try their combobox or dropdown components, the dropdown list doesn't appear when clicked on it. I use their examples from the docs, which compiles without errors. But none of their examples work out of the box, and no other information is provided.
The problem is that the dropdown list does not appear when clicked on. Not in Edge, not in Firefox. When I check the elements on the page, I do not see the html elements with the list items, although I can cycle through them with the arrow keys. The list appears from the side when the window is tablet format, and setting ResponsiveMode did nothing. Whith a normal screen however, nothing is displaying, and no onchange events are fired.
This is my code for the dropdown:
import { IStackTokens, ResponsiveMode, Stack } from '#fluentui/react';
import { Dropdown, DropdownMenuItemType, IDropdownOption, IDropdownStyles } from '#fluentui/react/lib/Dropdown';
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
const DropdownControlledMultiExampleOptions = [
{ key: 'fruitsHeader', text: 'Spooler status', itemType: DropdownMenuItemType.Header },
{ key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' },
{ key: 'grape', text: 'Grape' },
{ key: 'broccoli', text: 'Broccoli' },
{ key: 'carrot', text: 'Carrot' },
{ key: 'lettuce', text: 'Lettuce' },
];
export const DropdownList: React.FunctionComponent = () => {
const stackTokens: IStackTokens = { childrenGap: 20 };
return (
<Stack tokens={stackTokens}>
<Dropdown
placeholder="Select an option"
label="Disabled responsive"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
responsiveMode={ResponsiveMode.unknown}
/>
<Dropdown
placeholder="Select an option"
label="Responsive with panel"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
/>
</Stack>
);
};
Which I load in my app.tsx
function App() {
return (
<div className="App">
<DropdownList/>
</div>
);
}
Does anyone have an idea how I can get this to work? Or what is causing this?
EDIT and possible solution: It seems that removing the <React.Strict> tags in index.tsx does the job. Don't know why, but then the Fluid-UI controls work fine.

AntD Tree: need help! can't pass react element as icon OR title for antd tree

I'm using the AntD tree and I have a react element that I want to pass as either an icon or a title because it has custom styling. Due to it being IP I can't share too much code, but my question is:
how can I pass a react element (see below i.e. generic name) as either a title or icon and have antD tree render it?
i.e. this is what I want to pass as a prop to the icon or title
import React from 'react';
const genericName = (props) => {
// code uses props to get some infor for Color
// cant share code due to proprietary reasons
// but it is not needed for this question
const colorHTML = getColor(Color);
return (
<div>
<div className={`colors from`}>${colorHTML}</div>
{pin}
</div>
);
};
export default genericName;
in my console you can see node.icon is a typeof react.element. I want to target that and just pass the prop into antD tree as either title or icon
i.e.
return (
<Tree
icon={node.icon}
/>
)
I've searched and similar answers were given before antD forbid the use of children and strictly allows treeData. All examples I see only use strings in titles/icons, but since antD documentation is very limited, I need to know if my use case is possible. Right now, for the life of me I can't understand why it doesn't populate.
Thank you in advance.
It should definitely work to put a JSX component as title within treeData. Take a look at this snippet, I added a Icon here in one of the titles:
import React from 'react'
import { RightCircleOutlined } from '#ant-design/icons'
type Props = {}
import { Tree } from 'antd';
import type { DataNode, TreeProps } from 'antd/es/tree';
const treeData: DataNode[] = [
{
title: <span>{<RightCircleOutlined />} parent</span>, //icon added here
key: '0-0',
children: [
{
title: 'parent 1-0',
key: '0-0-0',
disabled: true,
children: [
{
title: 'leaf',
key: '0-0-0-0',
disableCheckbox: true,
},
{
title: 'leaf',
key: '0-0-0-1',
},
],
},
{
title: 'parent 1-1',
key: '0-0-1',
children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
},
],
},
];
const Demo: React.FC = () => {
const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
};
const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
console.log('onCheck', checkedKeys, info);
};
return (
<Tree
checkable
defaultExpandedKeys={['0-0-0', '0-0-1']}
defaultSelectedKeys={['0-0-0', '0-0-1']}
defaultCheckedKeys={['0-0-0', '0-0-1']}
onSelect={onSelect}
onCheck={onCheck}
treeData={treeData}
/>
);
};
export default Demo;

Unable to overwrite css top property in prime react menu component

I'm trying to get rid of the space as shown in the image below:
I'm using the Menu component of primereact from this documentation
Here's my constructor code for reference:
constructor() {
super();
this.state = {
items: [
{
label: 'First Services',
items: [
{label: 'firstitem',
command: (event) => {window.open('http://someurl','_blank');}},
{label: 'firstitemname',
command: (event) => {window.open('http://someurl#get-firstitemname','_blank');}},
{label: 'firstcategoryname',
command: (event) => {window.open('http://someurl#get-firstcategoryname','_blank');}},
]
},
{
label: 'Second Services',
items: [
{label: 'testforuser ',
command: (event) => {window.open('http://someurl#get-testforuser','_blank');}},
{label: 'testforproject',
command: (event) => {window.open('http://someurl#get-testforproject','_blank');}},
{label: 'testforprotocol ',
command: (event) => {window.open('http://someurl#get-testforprotocol','_blank');}}
]
},
{
label: 'Workflows ',
items: [
{label: 'Workflow for User ',
command: (event) => {window.open('http://someurl#workflow-section','_blank');}}
]
},
]
};
}
And here's my Menu and Button component defined:
<Menu
model={this.state.items}
popup={true}
style={{fontSize:'16px'},{width:'12%'}}
ref={el => this.menu = el}
/>
<Button
label="My DropDown Menu"
icon="pi pi-bars"
style={{width:'12%'},{backgroundColor:'#000000'}}
onClick={
(event)=>this.menu.toggle(event)
}
/>
I figured out the reason why there's space between the Button and the Menu. When I right clicked on the MY DROPDOWN MENU and selected Inspect Element Q on my Firefox browser, I saw the following-the css top property is set to 118.5px. :
I'm trying to overwrite the top property and change it to 60px from 118.5px. For that I tried modifying my code like this:
<Menu
model={this.state.items}
popup={true}
style={{fontSize:'16px'},{width:'12%'},{marginTop:'60px'}}
ref={el => this.menu = el}
/>
But it ended up showing as a separate property like this:
How can I modify top property?
Top and margin-top are 2 different things in CSS.
style={{
top:'60px'
}}
CSS: Top vs Margin-top
First check what classes are being used by the primereact menu, using console, then make a .css file and import into your .js file. Write the same name of the class as you found out using console and then override the properties you want. Then run your app again. It should work. P.S. I tried this before and this worked for me.

How to make the options in react-select dropdown accessible?

I am building a reactjs application and I am using a library called react-select for my dropdown which is searchable.
but the problem I am facing is that the options inside the select are not being read out by NVDA screenreader when using arrow keys.
and am not able to set focus on this dropdown as well for some reason.
I tried it via the official documentation but no luck as of now.
The library I am using:
React-select
https://react-select.com/home
The code:
import React, { Component, Fragment } from "react";
import Select from "react-select";
export const flavourOptions = [
{ value: "vanilla", label: "Vanilla", rating: "safe" },
{ value: "chocolate", label: "Chocolate", rating: "good" },
{ value: "strawberry", label: "Strawberry", rating: "wild" },
{ value: "salted-caramel", label: "Salted Caramel", rating: "crazy" }
];
export default class SampleDropdown extends Component {
state = {
isClearable: true,
isDisabled: false,
isLoading: false,
isRtl: false,
isSearchable: true
};
componentDidMount() {
document.getElementById("translate").focus();
}
render() {
const {
isClearable,
isSearchable,
isDisabled,
isLoading,
isRtl
} = this.state;
return (
<Fragment>
<Select
className="basic-single"
classNamePrefix="select"
defaultValue={flavourOptions[0]}
isDisabled={isDisabled}
isLoading={isLoading}
isClearable={isClearable}
isRtl={isRtl}
isSearchable={isSearchable}
name="color"
options={flavourOptions}
id="translate"
/>
</Fragment>
);
}
}
And here is a working example in codesandbox.
https://codesandbox.io/s/focused-clarke-euk0e
Actual result: When I enter the page, the dropdown does not have the focus. and am not able to read out options in the dropdown using arrow keys in NVDA screenreader.the options are being read out as blank.
Expected result: When I enter the page, the dropdown should have the focus. and the options in the dropdown should be read out when using arrow keys when NVDA screenreader is switched on.
I looked at using the same library but ran into accessibility issues as well. I ended up building my custom select element and manually handling the key presses, focus movement, and label announcements. If you're stuck on using react-select you'll probably need to amend it yourself or wait for a PR.
Otherwise, if you're up for the challenge, you can follow my tutorial on creating an accessible select component in React. You can pull apart the code on codesandbox as well. This might make it easier to port to the react-select as well.
And of course, I'd also recommend using the native select element, as that will handle accessibility best.
Reach UI has accessible components. This Combobox could be of use https://reach.tech/combobox

how to make a message without wrapping in span in react-intl

i have a problem with yahoo/react-intl thats i want to make messages in string type but when im using FormattedMessage it gives me message wrapped in span and thats not cool.
i tried formatMessage and that not working too.
i be very thankful for any help or advise this is my code:
import React from 'react';
import {FormattedMessage} from 'react-intl';
export default {
items: [
{
name: <FormattedMessage id='app.dashboard'/>,
url: '/dashboard',
icon: 'icon-speedometer',
badge: {
variant: 'info',
text: 'New',
},
},
{
title: true,
name: <FormattedMessage id='app.dashboard'/>,
// optional wrapper object
wrapper: {
// required valid HTML5 element tag
element: 'strong',
// optional valid JS object with JS API naming ex: { className: "my-class", style: { fontFamily: "Verdana" }, id: "my-id"}
attributes: {},
},
// optional class names space delimited list for title item ex: "text-center"
class: '',`enter code here`
},
for use in jsx:
it's rendered as a <span>:
<FormattedMessage id='app.dashboard'/>
it's rendered as an <option>:
<FormattedMessage id='app.dashboard' children={msg=> <option>{msg}</option>}/>
or:
<FormattedMessage id='app.dashboard' tagName="option"/>
it's rendered to nothing:
<FormattedMessage id='app.dashboard' children={msg=> <>{msg}</>}/>
or:
<FormattedMessage id="app.dashboard">{txt => txt}</FormattedMessage>
To use it in a component, you can use formatMessage() like this:
const App=()=>{
const value = intl.formatMessage({ id: 'header.nav.login' });
return(<div>{value}</>)
}
Given that you inject the intl context by yourself, Then you can use the formatMessage function.
For example, in your case:
items: [
{
name: intl.formatMessage({id:'app.dashboard'});
}
]
To get intl in your component you have two choices:
get it from your component's context
use injectIntl to get it in your props.
If you're not in a component, it gets slightly harder but I would just put the id instead of the formatted message in name and then use the react-intl context when available. Here, in the component that consumes and displays this list of items.
The solution here is to upgrade react-intl to version 3.
In version 3, the <FormattedMesage> (and similarly others react-intl components) is rendering into React.Fragment.
If you want to render it to something else you can specify textComponent prop on IntlProvider, eg.:
<IntlProvider textComponent="span" />
See info in Migration Guide (v2 -> v3).

Resources