React-router uses ... type components to create SPA-type navigation events. If I wrap any kind of material-ui button with Link, it works fine in Chrome, but not in Safari. In Safari, no navigation events happen. A workaround is to add an explicit onTouchTap
handler on the button itself, but I believe this is some kind of bug.
@mariusk Could you please tell me how did you add the Link component from react-router to Button component. For example, if I do something like the following it doesn't work.
let editLink = <Link to="editTopic"/>;
<IconButton
linkButton={true}
onTouchTap={editLink}
tooltip="Edit forum">
<i className="material-icons">edit</i>
</IconButton>
I notice that if I add linkButton={true}
I need to add the route to href
element, but react router Link generates the anchor tag by default.
Here's the actual code:
<Link to="/login"><FlatButton onTouchTap={this.clickHandler}>{l.l('no', 'Sign in')}</FlatButton></Link>
Without the onTouchTap handler, it works in Chrome but not in Safari. With the explicit handler (which again calls react-router's transitionTo(...)
it also works in safari.
This might be because FlatButton generates a <button />
element and I believe <Link />
generates an <a />
element. So you'll have:
<a><button /></a>
One solution that I can think of is to change enhanced-button to accept an element prop that will allow users to customize the container element. So you'll be able to do:
<FlatButton containerElement={<Link to="/login"/>} />
You're right; button inside an a element is not valid html5. Another possible solution would be to have the button styles available for a
elements (in addition to button
), and then simple style it with className
.
Actually with #846, you'll be able to do:
<FlatButton>
<Link to="/login/" />
</FlatButton>
I just tested #846. It broke the styling (button text is white on white), and the link isn't active (doesn't work). Here's the actual code I tested:
<FlatButton><Link to="/login">{l.l('no', 'Sign in')}</Link></FlatButton>
In addition to the color issue (which was caused by my own styling), and the fact that the link still does not work, there's also a focus issue. When hovering over the embedded a
link, only the link parts gets highlighted, not the whole button.
@mariusk You should be able to do this now:
<FlatButton
containerElement={<Link to="/login" />}
linkButton={true}
label={l.l('no', 'Sign in')}/>
That looks and works perfect, thanks, great work!
When I switch to this I am getting EventEmitter memory leak warnings. I'm not sure whether it is the click handlers on <Link>
or those on <EnhancedButton>
which are not being removed properly? Maybe <Link>
is not being properly unmounted?
Looks like it's now working even without linkButton={true}
, right? When the button has Link
for containerElement
it is turned into a <a>
element rather than a <button>
?
@hai-cea nice, thx!
@antoinerousseau yes, turn into <a>
, broke the one style... the text originally set to text-align: center
's changed into left..as its now a <a>
element
containerElement is not documented :(
I see that this setup (e.g. RaisedButton
width containerElement={<Link to="/register>}
has CSS issue. Ripple effect is not firing properly, Actually it's firing but with so much delay that I nearly can't see it (until I tap longer such button). I'm using v0.15.4.
Any hint how to speed it up?
Doesn't work any longer
Warning: Unknown prop
linkButton
on tag. Remove this prop from the element.
@wzup just remove the linkButton={true}
@wzup If you write your code like this without linkButton prop, it should work.
<FlatButton
containerElement={<Link to="/login" />}
/>
@hai-cea ,
hello,
how can i make a function on login page [say modal function] to popup,in the above code once it navigates after button click
Pardon the bump but the following still generates a warning on 0.17:
<RaisedButton
label="Sign In"
containerElement={<Link to="/login" />}
/>
Generates the following:
Warning: Unknown prop onTouchTap
on tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
I had the same problem, so I created a reusable component that works for me.
import React from 'react';
import {Component, PropTypes} from 'react';
import FlatButton from 'material-ui/FlatButton';
export default class FlatLinkButton extends Component {
static propTypes = {
...FlatButton.propTypes,
to: PropTypes.string.isRequired,
link: PropTypes.func.isRequired,
label: PropTypes.node.isRequired,
};
render() {
const style = Object.assign({
color: 'white',
marginTop: '7px'
}, this.props.style);
const props = {
...this.props,
style,
};
delete props.to;
delete props.link;
const Link = this.props.link;
return (
<Link to={this.props.to}>
<FlatButton {...props}/>
</Link>
);
}
}
Usage:
import {Link} from 'react-router';
import FlatLinkButton from './FlatLinkButton';
<FlatLinkButton to="/login" link={Link} label="Login"/>
@MatthewEdge #4670 should solve the issue
In Material UI v1.0.0-alpha20, this does not seem to work for me:
<Button color="contrast" containerElement={<Link to="/login" />} linkButton={true} >
Login
</Button>
Hi,
same problem, using v1.0.0-alpha21 for prototyping and got the message containerElement
is unknown. So the property seems dropped and I ended up with this solution:
<Button raised dense color="primary" onClick={() => this.props.history.push('/project/4711')}>
<i className="fa fa-search fa-on-button" aria-hidden="true" />Search
</Button>
@HerrVoennchen with the latest version v1.0.0-beta.3
you should be able to do:
const LinkWrapper = ({ ...props }) => (
<Link {...props} />
)
And then use the wrapper as the component
<Button to={`/project/${id}`} component={LinkWrapper}>Go</Button>
Thanks for the pointer @HiroAgustin; this seems to work in v1.0.0-beta.3
:
<Button
color="primary"
to={`/projects/${project.id}`}
component={props => <Link {...props}/>}
>View</Button>
In 1.0.0-beta.6
using @HiroAgustin and @hubgit's solution I'm getting a warning:
Warning: Material-UI: please provide a class to the component property.
The keyboard focus logic needs a reference to work correctly.
Any suggestions?
@m-h-t for me it worked when I removed the curly braces:
<Button
component={Link}
to="/customers">
Customers
</Button>
@limakayo But what do you do when you would like to dynamically create the link?
@m-h-t good question, I tested with the curly braces now and it worked, I don't know why
anyone does know how to add a
<AppBar
title={"Travel Agency"}
iconElementRight={
<div>
<Link to="/customers" className="navbar"><FlatButton label="Customers" /></Link>
<Link to="/tours" className="navbar"><FlatButton label="Tours" /></Link>
</div>
}
/>
we can just use like this with v1-beta
<Button
component={({...props}) => <Link to='/path' {...props} />}
>Path</Button>
I think material-ui belong still old style ui frameworks , where you can't find all the button styles that you find, or simple are too much styles, if someone need customize in a low level like me , finally I'm happy with 'styled-components' no need more about css, saas,etc, just react pure components.. you lost a lot of time, days, hours, trying figure out how or where change something of if there is a bug, or wait the future release ..
@palaniichukdmytro thanks for the solution, but it breaks the ripple styling in BottomNavigationAction
This worked for me on a material-ui button:
```
import React from 'react'
import Button from '@material-ui/core/Button'
import { Link } from 'react-router-dom'
const SubmitButton = () =>
type="submit"
fullWidth
variant="contained"
color="primary"
component={Link}
to="/form"
>
Submit Form
Tried to render button with Link with the code below, but nothing's getting rendered on the view:
<Button
component={() => (
<Link
to={{
pathname: 'hello-there',
state: {
hello: 'HELLO THERE!',
},
}}
/>
)}
size="small"
variant="contained"
color="primary"
fullWidth={true}
>
HELLO BUTTON
</Button>
How else can I pass props along to the next route using material-ui?
component={() => (
to={{
pathname: 'hello-there',
state: {
hello: 'HELLO THERE!',
},
}}
/>
)}
size="small"
variant="contained"
color="primary"
fullWidth={true}
>
HELLO BUTTON
I have the same question - ever solve this?
Most helpful comment
@mariusk You should be able to do this now: