Material ui dropdown and other controls doesnt work propertly - reactjs

I have an issue with the material-ui lib, where the dropdowns and menu doesnt work.
My code is the following.
import React from 'react';
import {Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarTitle} from 'material-ui/Toolbar';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';
import injectTapEventPlugin from 'react-tap-event-plugin';
class Interruptions extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 1
};
injectTapEventPlugin();
}
handleChange(event, index, value) {
this.setState({value: value});
}
render(){
return (
<div className="interruptions__wrapper">
<Toolbar>
<ToolbarGroup firstChild={true}>
<DropDownMenu value={this.state.value} openImmediately={true} onChange={this.handleChange}>
<MenuItem value={1} primaryText="All Broadcasts" />
<MenuItem value={2} primaryText="All Voice" />
<MenuItem value={3} primaryText="All Text" />
<MenuItem value={4} primaryText="Complete Voice" />
<MenuItem value={5} primaryText="Complete Text" />
<MenuItem value={6} primaryText="Active Voice" />
<MenuItem value={7} primaryText="Active Text" />
</DropDownMenu>
</ToolbarGroup>
<ToolbarGroup>
<ToolbarTitle text="Options" />
</ToolbarGroup>
</Toolbar>
</div>
);
}
}
export default Interruptions;
And this is my main where i render the app in the html.
import React from 'react';
import ReactDOM from 'react-dom';
import Interruptions from '../components/Interruptions.jsx';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import {red500} from 'material-ui/styles/colors';
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
const muiTheme = getMuiTheme({
palette: {
textColor: red500,
}
});
const InterruptionsApp = () => (
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<Interruptions />
</MuiThemeProvider>
)
ReactDOM.render(<InterruptionsApp />, document.getElementById('myInterruptions'));
Im using openImmediately={true} to see if atleast the menu is showing up (and it does) but when i try to click on it to open it again it doesnt show.
Thanks in advice.

#Jeff McCloud is right. You should injectTapEventPlugin() before you are first use the render function from React-DOM.
I don't know how you build your application webpack or browserify?
I run in this issue too. Be sure that you have declared React, React-DOM, react-tap-event-plugin and all the React addons which you are using to the external libs. I am building a vendor.js for instance.
This approach prevents that you have multiple version of React in your project which could also produce this kind of behavior.

Related

Component to call all material-ui Icon in React

I want to implement a component which calls the corresponding icon from material-ui. I've made it work when manually calling it.
import MenuIcon from '#material-ui/icons/Menu';
export const Icon = (props) => {
return (
<div>
<MenuIcon/>
</div>
)
}
The problem is I don't know how to change the import for all icons.
I want to call this component the following way:
<Icon icon="MenuIcon" className="someClass" />
<Icon icon="LocationOn" className="someClass" />
<Icon icon="Notifications" className="OthersomeClass" />
I can't figure out how to import all icons and how to change my Icon component to work for any icon from the material-ui package.
Something like this...
import React from 'react';
import * as IconList from '#material-ui/icons/Menu'; //error
export const Icon = (props) => {
const {icon, className} = props;
return (
<`${icon}` className={className} /> {//error}
)
}
Any ideas?
You should be able to import all the icons using named imports or the star imports (* as).
Star imports should look like this
import * as Icons from "#material-ui/icons";
<Icon icon={Icons.Menu} className="someClass" />
<Icon icon={Icons.AccessAlarmIcon} className="someClass" />
Named imports should look like this
import { Menu, AccessAlarmIcon } from "#material-ui/icons";
<Icon icon={Menu} className="someClass" />
<Icon icon={AccessAlarmIcon} className="someClass" />
You can also refactor your Icon component to utilize the React children prop, that way you can better compose each icon on the Icon component.
So it should look something like this
import React from 'react';
export const Icon = ({ children }) => {
return (
<>{children}</>
)
}
Then you can use it like this
<Icon>
<Menu className="someClass" />
</Icon>
<Icon>
<AccessAlarmIcon className="someClass" />
</Icon>
PS:
Your star imports were from '#material-ui/icons/Menu' as opposed to just '#material-ui/icons' and that caused an error

How to make react-admin default theme RTL

I need to make react-admin which uses material-ui underneath into RTL, so far nothing works because there are styles on each element overriding dir="rtl" on body tag, creating a custom theme like:
const theme = {
direction: 'rtl',
isRtl: true
};
const themeWithDirection = createMuiTheme({...defaultTheme, ...theme});
and using it on Admin component like:
<Admin locale="ar" dataProvider={dataProvider} i18nProvider={i18nProvider} theme={themeWithDirection} layout={layout}>
did not work. also usign StyleProvider on custom layout did not work:
import React from 'react';
import { Layout } from 'react-admin';
import { create } from 'jss';
import rtl from 'jss-rtl';
import { jssPreset } from '#material-ui/core/styles';
import { StylesProvider } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const MyLayout = props =>
<StylesProvider jss={jss}>
<Layout
{...props}
/>
</StylesProvider>;
The problem is that components like TextField use text-align: left;, so how can I flip their css without overriding them in a custom css file?
Using the ListGuesser I had no luck switching the grid to RTL, however, after writing a custom list component and JssProvider it now works:
import React from 'react';
import { List, Datagrid, TextField, EmailField } from 'react-admin';
import { create } from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import { jssPreset } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
export const UserList = props => (
<JssProvider jss={jss}>
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<TextField source="name" />
<TextField source="username" />
<EmailField source="email" />
<TextField source="address.street" />
<TextField source="phone" />
<TextField source="website" />
<TextField source="company.name" />
</Datagrid>
</List>
</JssProvider>
);

Can't include React UI frameworks (Grommet)

I have problems importing UI libraries, I had problem with ant design library so I decided to try different one, now I have problem importing Grommet.
What am I doing wrong? I added dependencies according documentation and added examples included in documentation yet still not working.
I am trying to execute this code from documentation
But it doesn't look the same at all
I work with codesandbox.io, here is link for the code on it
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import Heading from "grommet/components/Heading";
import Box from "grommet/components/Box";
import Header from "grommet/components/Header";
import Title from "grommet/components/Title";
import Search from "grommet/components/Search";
import Menu from "grommet/components/Menu";
import Anchor from "grommet/components/Anchor";
import "grommet-css";
class HelloWorldApp extends React.Component {
render() {
return (
<div>
<Header>
<Title>Sample Title</Title>
<Box flex={true} justify="end" direction="row" responsive={false}>
<Search
inline={true}
fill={true}
size="medium"
placeHolder="Search"
dropAlign={{right: "right"}}
/>
<Menu dropAlign={{right: "right"}}>
<Anchor href="#" className="active">
First
</Anchor>
<Anchor href="#">Second</Anchor>
<Anchor href="#">Third</Anchor>
</Menu>
</Box>
</Header>
<Box>
<Heading>
Hello, I'm a Grommet Component styled with
grommet-css
</Heading>
</Box>
</div>
);
}
}
var element = document.getElementById("root");
ReactDOM.render(<HelloWorldApp />, element);
So according to your code:
<Menu dropAlign={{right: "right"}}>
was missing the icon attribute, without which the Menu component directly renders the Anchor, the menu-items component.
add import for the icon of your choosing, i.e: Actions ( from the example )
import Actions from 'grommet/components/icons/base/Actions';
add the icon attribute to the Menu component:
<Menu
icon={<Actions />}
dropAlign={{ right: 'right' }}
>
<Anchor href="#" className="active">First</Anchor>
<Anchor href="#">Second</Anchor>
<Anchor href="#">Third</Anchor>
</Menu>
here's a codesandbox.io link which fixes your issue:
https://codesandbox.io/s/237xo7y48p

Controlled TextField loosing focus after every character from keyboard

Whenever I input a character into the field the focus goes away.
How do I correct that?
"use strict"
import React from "react";
import createReactClass from "create-react-class";
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
export var Config = createReactClass({
setConfig: function() {
localStorage.serverUrl=this.owner.state.serverUrl;
location.reload();
},
setUrl: function(evt) {
this.owner.setState({serverUrl: evt.target.value});
},
render: function() {
var {owner}=this.props;
this.owner=owner;
return <div>
<CardTitle title={__("Server")} />
<CardText>
<TextField id="serverUrl" floatingLabelText={__("Server URL")} value={owner.state.serverUrl} onChange={this.setUrl} />
</CardText>
<CardActions>
<RaisedButton label={__("Apply")} onTouchTap={this.setConfig} />
</CardActions>
</div>;
}
});
There are of course other elements on the root of the application (the actual logic is a bit more complicated, here only the structure):
<MuiThemeProvider muiTheme={muiTheme}>
<div>
<AppBar title={__("Demo")}
iconElementRight={right}
onRightIconButtonClick={this.logon}
onLeftIconButtonClick={this.toggleMenu} />
<Drawer open={this.state.menuOpen}
docked={false}
onLeftIconButtonTouchTap={this.toggleMenu}
onTouchTap={this.toggleMenu}>
<RaisedButton onTouchTap={this.toggleMenu} label={__("Menu")} />
<Menu>
<MenuEntry owner={this} value="/config" title={__("Server")} />
<MenuEntry owner={this} value="/logon" title={__("Logon")} />
<Divider />
<MenuEntry owner={this} value="/about" title={__("About")} />
</Menu>
</Drawer>
<Paper>
<Config owner={this} />
</Paper>
</div>
</MuiThemeProvider>;
Here the implementation MenuEntry
"use strict";
import React from "react";
import createReactClass from "create-react-class";
import MenuItem from 'material-ui/MenuItem';
export var MenuEntry=createReactClass({
onChange: function() {
this.owner.setState({menuOpen: false, systemMenuOpen: false, location: this.value});
},
render: function() {
var {title, owner, value, color}=this.props;
this.owner=owner;
this.value=value;
var selected=(owner.state.location==value);
return <MenuItem checked={selected} onTouchTap={this.onChange} backgroundcolor={color}>
{title}
</MenuItem>;
}
});
Versions:
Material-UI: 0.20
React: 16.2.0
Browser: Chrome 63.0.3239.123 (Mac & Windows & Android)
FF 57.0.4 (Mac & Windows)
As mentionned in material-ui docs about the onChange prop of <TextField> :
Signature: function(event: object, newValue: string) => void
event: Change event targeting the text field.
newValue: The new value of the text field.
So i think you should remove setUrl method and change <TextField> like this (no need to use onBlur) :
<TextField id="serverUrl" floatingLabelText={__("Server URL")} value={owner.state.serverUrl} onChange={(evt, value) => this.owner.setState({ serverUrl: value })} />
More comments about the code :
I'm maybe wrong but calling the setState method of a parent component passed in props seems a bad practice to me, you should consider handling the state of the input in the state of Config component.
Also, you're using create-react-class instead of a class component, it seems useless to use it in your case (you're using es6 import while create-react-class is used to build react app without es6) see official docs for more infos.
Edit : I'm able to reproduce a minimal working example :
Config.js :
import React from 'react';
import createReactClass from 'create-react-class';
import TextField from 'material-ui/TextField';
export var Config = createReactClass({
setUrl: function(evt, value) {
this.owner.setState({ serverUrl: value });
},
render: function() {
var { owner } = this.props;
this.owner = owner;
return (
<div>
<TextField
id="serverUrl"
floatingLabelText={'Server URL'}
value={owner.state.serverUrl}
onChange={this.setUrl}
/>
</div>
);
},
});
index.js :
import React, { Component } from 'react';
import createReactClass from 'create-react-class';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { render } from 'react-dom';
import { Config } from './Config';
var App = createReactClass({
getInitialState: function() {
return { serverUrl: 'test' };
},
render: function() {
console.log(this.state.serverUrl);
return (
<MuiThemeProvider>
<Config owner={this} />
</MuiThemeProvider>
);
},
});
render(<App />, document.querySelector('#root'));
I guess the issue is with Textfield value props and onBlur. The state value that you are passing to value prop is incorrect i.e., value={owner.state.serverUrl} it should be value={this.owner.state.serverUrl}.
The onBlur fuction doesn't exist in your code but you trying to call onBlur={this.onBlur} which should be removed from TextField component. It seems onBlur is not a valid prop to TextField as per material UI docs
<TextField id="serverUrl" floatingLabelText={__("Server URL")} value={this.owner.state.serverUrl} onChange={(evt, value) => this.owner.setState({ serverUrl: value })} />

How to add Multiple Buttons in AppBar using iconElementRight

<AppBar
title={<span>Title</span>}
iconRightElement={
<FlatButton key={1} label="About"/>
<FlatButton key={2} label="Home" />
} />
/>
I have tried above code but not working..
Add one parent element
<div>
<FlatButton key={1} label="About"/>
<FlatButton key={2} label="Home" />
<div>
The solution in my opinion would be to wrap all your buttons/icons in one single element and then pass it to your AppBarcomponent via the attribute iconRightElement.
See full example below. Hope this helps:
import Link from 'next/link'
import React, {PropTypes} from 'react'
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import IconButton from 'material-ui/IconButton';
import AppBar from 'material-ui/AppBar';
import NavigationClose from 'material-ui/svg-icons/navigation/close';
import ActionHome from 'material-ui/svg-icons/action/home';
import FlatButton from 'material-ui/FlatButton';
import FontIcon from 'material-ui/FontIcon';
const rightButtons = (
<div className="appBarIcons">
<Link href="/">
<IconButton><ActionHome style={buttonStyle}/></IconButton>
</Link>
<Link href="/Login">
<FlatButton label="Login" style={buttonStyle}/>
</Link>
</div>
);
const buttonStyle = {
color: 'white'
}
class Header extends React.Component {
render(){
return (
<div>
<MuiThemeProvider>
<div>
<AppBar
title="AppTitle"
iconClassNameRight="muidocs-icon-navigation-expand-more"
iconElementRight={rightButtons}
/>
</div>
</MuiThemeProvider>
</div>
)
}
}
export default Header

Resources