I'm discovering ReactJS and material-ui (http://material-ui.com/).
I try to create a default template for my application. I want to use an AppBar and a LeftNav (renamed in Drawer in new versions) in separated components.
The AppBar has a menu button on it by default. I want to use it to open the LeftNav but I don't know how I can call my LeftBarComponent component function to open it.
I've almost understood how to communicate between components but in my case, I don't know how I could do because there is no documentation about it. The only thing I know to open the LeftNav element is to use LeftNav.toggle()
http://material-ui.com/#/components/left-nav
Thanks for your help.
Default.jsx
use strict';
var React = require('react');
var pageStore = require('../../stores/page');
var MainNavbar = require('../modules/navbar.jsx');
var LeftNavbar = require('../modules/leftbar.jsx');
var getState = function() {
return {
title: pageStore.get().title
};
};
var DefaultComponent = React.createClass({
mixins: [pageStore.mixin],
componentDidMount: function() {
pageStore.emitChange();
},
getInitialState: function() {
return getState();
},
render: function() {
return (
/* jshint ignore:start */
<div className="main-container">
<MainNavbar />
<LeftNavbar />
<div className="content">
{this.props.children}
</div>
</div>
/* jshint ignore:end */
);
},
// Event handler for 'change' events coming from store mixins.
_onChange: function() {
this.setState(getState());
}
});
module.exports = DefaultComponent;
navbar.jsx
'use strict';
var React = require('react');
var routeActions = require('../../actions/routes');
var MUI = require('material-ui');
var AppBar = MUI.AppBar;
// Navbar Component
// Application main menu
// Usage: <Navbar />
var NavbarComponent = React.createClass({
render: function() {
return (
/* jshint ignore:start */
<AppBar title="MyApp" onMenuIconButtonTouchTap={ this._handleClick }>
<div className="clear"></div>
</AppBar>
/* jshint ignore:end */
);
},
_handleClick: function()
{
console.log('ok');
}
});
module.exports = NavbarComponent;
leftbar.jsx
'use strict';
var React = require('react');
var routeActions = require('../../actions/routes');
var MUI = require('material-ui');
var LeftNav = MUI.LeftNav;
var MenuItem = MUI.MenuItem;
var menuItems = [
{ route: 'home', text: 'Home' },
{ route: 'about', text: 'About' },
];
// LeftBar Component
// Application left menu
// Usage: <LeftBar />
var LeftBarComponent = React.createClass({
render: function() {
return (
/* jshint ignore:start */
<LeftNav menuItems={menuItems} docked={false} />
/* jshint ignore:end */
);
},
_handleClick: function()
{
console.log('ok');
}
});
module.exports = LeftBarComponent;
In this case you need to pass the event upwards through your components, and then down again.
<MainNavbar onClickMenu=this.onClickMenu/>
<LeftNavbar isOpen=this.state.leftNavIsOpen/>
However, using this in conjunction with Reactjs is not optimal, as the LeftNav material component does not react to attributes, but to method calls like you were saying.
To work around, you could put a check in the LeftNav render method, that checks the current state, and calls toggle() if needed. In principle this goes against the React way of thinking, as a state is contained inside the specific child component and not in the DefaultComponent that handles it.
render:function(){
if(this.props.isOpen){
LeftNav.open();
}
return ...
To clarify what steinso said, you need to send the event to an Action using the Flux architecture and then change it in a Store. Then dispatch an emit change event with EventEmitter. This will fire off a render on the effected components with the updated state.
https://facebook.github.io/flux/
If you must have them separated then, that would be the best way. However, if you can have them in the same component, such as 'Main' then, you can simply use a ref attribute and reference the component.
module.exports = React.createClass({
childContextTypes: {
muiTheme: React.PropTypes.object
},
getChildContext: function() {
return {
muiTheme: ThemeManager.getCurrentTheme()
};
},
_toggleNav: function(){
this.refs.leftNav.toggle();
},
render: function() {
return (
<div>
<mui.LeftNav
ref='leftNav'
menuItems={menuItems}
docked={false} />
<mui.AppBar
title='Default'
onLeftIconButtonTouchTap={this._toggleNav} />
</div>
);
}
});
Like so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With