With the help of the community, I have been able to final have my modal pop-up working on my reat website.
The modal code is as below:
import React from "react";
import '../../assets/styles/GenericTheme.css'
import { Modal, Button } from "react-bootstrap";
class LoginRegisterModal extends React.Component {
constructor(props, context) {
super(props);
this.state = {show: false};
}
open = () => {
this.setState({show: true});
}
close = () => {
this.setState({show: false});
}
componentDidUpdate(prevProps) {
const { show } = this.props;
if (prevProps.show !== show) {
if (show) {
this.open(); // open if parent says to
} else {
this.close(); // close if parent says to
}
}
}
render() {
const styleModal = {
width:770,
height:480,
backgroundColor:"#ffffffff",
borderRadius:21.5,
boxShadow: "0px 8px 18px 0 rgba(0,0,0,0.14)",
}
return (
<Modal show={this.state.show} style={styleModal} >
<Modal.Body>test</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.close}>
Close
</Button>
</Modal.Footer>
</Modal>
);
}
}
export default LoginRegisterModal;
The modal is called by the react-bootstrap Navs components:
const menuLoginRegister = <Nav.Link ref="LoginRegisterModal" eventKey={1} href="#" onClick={this.openLogin}>{TextContents.MenuLoginRegister}</Nav.Link>;
And I have added the modal in the return function like below:
return (
<div>
<Navbar className="village-header" width="100" expand="lg">
....
</Navbar>
<LoginRegisterModal show={this.state.showLogin}
onHide={() => this.setState({ showLogin: false })}/>
</div>
);
The only issues is that the modal keep being displayed on the top left corner and not centered in the screen.
I tried to use a center in the style but it still not move it to the center.
Any idea how to do it ?
Thanks
Related
I have made a draggable split panel by https://github.com/johnwalley/allotment.
I would like to make the background of the pane below green. But after dragging the split, the background color is not systematically updated in that area.
Does anyone know how to amend the code to achieve that?
https://codesandbox.io/s/reset-forked-rfifun?file=/src/App.js
import React from "react";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import styles from "./App.module.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
toExpand: true
};
this.myRef = React.createRef();
}
handleChange = (sizes) => {
if (sizes.length > 1) {
if (sizes[1] < 31) {
this.setState({ toExpand: true });
} else {
this.setState({ toExpand: false });
}
}
};
render() {
return (
<div>
<div className={styles.container}>
<Allotment vertical onChange={this.handleChange} ref={this.myRef}>
<Allotment.Pane>Main Area</Allotment.Pane>
<Allotment.Pane preferredSize="0%">
<div
style={{ backgroundColor: "green" }}
onClick={() => {
if (this.state.toExpand) {
this.myRef.current.resize([50, 50]);
} else {
this.myRef.current.resize([10000, 0]);
}
}}
>
Console
{this.state.toExpand ? "ArrowUp" : "ArrowDown"}
</div>
</Allotment.Pane>
</Allotment>
</div>
</div>
);
}
}
It seems that the content div can be set to take full height of the panel:
Forked demo with modification: codesandbox
<Allotment.Pane preferredSize="0%">
<div
// 👇 Set the content div to take full height
style={{ backgroundColor: "green", height: "100%" }}
onClick={() => {
if (this.state.toExpand) {
this.myRef.current.resize([50, 50]);
} else {
this.myRef.current.resize([10000, 0]);
}
}}
>
Console
{this.state.toExpand ? "ArrowUp" : "ArrowDown"}
</div>
</Allotment.Pane>;
My sidebar in the responsive mode not working correctly, i'm use #media for controller width of page, when is responsive i use position:absolute for sidebar button stay in up of content, i created a state for onclick is active change this position:relative but is not working, help please. The page in the mode normal funciton correctly, and mode responsive (Ctrl + shift + I) too but i click in the button the problemn happens.
Sidebar.js
export default class Menu extends Component {
constructor(props) {
super(props);
this.state = {
classStyle: "sidebar"
};
}
// handleSidebar(value) {
// this.setState = ({ classStyle : value });
// }
handleSidebar = (value) => {
this.setState = ({ classStyle: value });
}
render() {
return (
<div className={this.state.classStyle}>
<Navbar bg="light" variant="light" sticky="top" expand="lg">
<Navbar.Toggle aria-controls="navbarSupportedContent" onClick={() => handleSidebar("sidebarR")} />
<Navbar.Collapse id="navbarSupportedContent">
Index.css
#media (max-width: 600px)
{
.sidebar
{
position: absolute;
}
.sidebarR
{
position: relative;
}
}
Please try this one, it is working
Replace this function in your component
handleSidebar = () => {
console.log("clicked");
this.setState({ classStyle: "sidebarR" });
}
If you want toggle class then use below function,
handleSidebar = () => {
console.log("clicked");
const classStyle = this.state.classStyle == "sidebar" ? "sidebarR" : "sidebar";
this.setState({ classStyle: classStyle });
}
Running Component without Navbar Component,
import React,{Component} from 'react';
import './Menu.css';
export default class Menu extends Component {
state = {
classStyle: "sidebar"
};
handleSidebar = () => {
console.log("clicked");
this.setState({ classStyle: "sidebarR" });
}
render() {
return (
<div className={this.state.classStyle}>
<p onClick={() => this.handleSidebar()} >Menu</p>
</div>
)
}
}
When you call handleSidebar on onClick, you need to use this
Navbar.Toggle aria-controls="navbarSupportedContent" onClick={() => this.handleSidebar("sidebarR")} />
I have a separate App.css file that has global css attributes and have classes for responsiveness. The issue is I want to render elements differently for separate devices but can't seem to figure out how to do that as using conditionals isn't applying as such.
import UserItem from "./UserItem";
import Spinner from "../layout/Spinner";
import PropTypes from "prop-types";
const Users = ({ users, loading }) => {
if (loading) {
return <Spinner />;
} else {
return (
<div style={userStyle} className='body'>
{users.map((user) => {
return <UserItem key={user.id} user={user} />;
})}
</div>
);
}
};
const windowWidth = window.innerWidth;
Users.propTypes = {
users: PropTypes.array.isRequired,
loading: PropTypes.bool.isRequired,
};
const userStyle = {
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gridGap: "1rem",
};
export default Users;
My css #media query which I am trying to apply to effect change on a small device.
/* Mobile Styles */
#media (max-width: 700px) {
.hide-sm {
display: none;
}
}
How do I implement this #media css style so that it can render the page differents through jsx?
You can use material ui. that will fulfil your requirement. Please check this example:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import { green } from '#material-ui/core/colors';
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(1),
[theme.breakpoints.down('sm')]: {
backgroundColor: theme.palette.secondary.main,
},
[theme.breakpoints.up('md')]: {
backgroundColor: theme.palette.primary.main,
},
[theme.breakpoints.up('lg')]: {
backgroundColor: green[500],
},
},
}));
export default function MediaQuery() {
const classes = useStyles();
return (
<div className={classes.root}>
<Typography variant="subtitle1">{'down(sm): red'}</Typography>
<Typography variant="subtitle1">{'up(md): blue'}</Typography>
<Typography variant="subtitle1">{'up(lg): green'}</Typography>
</div>
);
}
Material UI
You can use following example too.
class Card extends Component {
constructor() {
super();
this.mediaQuery = {
desktop: 1200,
tablet: 768,
phone: 576,
};
this.state = {
windowWidth: null
};
}
componentDidMount() {
window.addEventListener('resize', () => {
this.setState({windowWidth: document.body.clientWidth})
});
}
render() {
return (
<div style={{
width: this.state.windowWidth > this.mediaQuery.phone
? '50%'
: '100%',
//more styling :)
}}>
<!-- <Card> contents -->
</div>
);
}
}
Source
I suggest that use CSS #media query to make responsive layouts.
But if you insist on implement with JS and React you should get windowWidth after component mounted. You can use useEffect hook to do so and save value in a state:
const [windowWidth, setWindowWidth] = useState('');
useEffect(() => {
setWindowWidth(window.innerWidth) // or better one -> window.clientWidth
});
I'm sure this has been asked before however, I can't find the answer. How do you get the Nav menu to close when you click on a NavLink in reactstrap or is this still in development?
Reactstrap has an isOpen parameter in state, so you need to set it to false
constructor(props) {
super(props);
this.closeNavbar = this.closeNavbar.bind(this);
this.state = {
isOpen: false
};
}
closeNavbar() {
this.setState({
isOpen: false
});
}
// and in Link or a element add onClick handler like this
<Link to="/" onClick={closeNavbar}>Home</Link>
Here is the code I use:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import library from './FontAwesomeLibrary';
import logo from '../../assets/images/logo.svg';
import {
Collapse,
Navbar,
NavbarToggler,
Nav,
NavItem } from 'reactstrap';
class Topbar extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.closeNavbar = this.closeNavbar.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this.state = {
isOpen: false,
};
}
componentWillMount() {
document.addEventListener('mousedown', this.handleClickOutside);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClickOutside);
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
closeNavbar() {
this.setState({
isOpen: false
});
}
handleClickOutside(event) {
const t = event.target;
if (this.state.isOpen && !t.classList.contains('navbar-toggler')) {
this.closeNavbar();
}
}
render() {
return (
<div className="topbar">
<section className="container">
<Navbar color="light" className="header" expand="md">
<Link className="locoLink" to="/"><img src={logo} className="logo" alt="logo" /></Link>
<Link to="/" className="logoCompany">Redux Blog</Link>
<NavbarToggler onClick={this.toggle}>
<FontAwesomeIcon icon={this.state.isOpen ? "times" : "bars"}/>
</NavbarToggler>
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="ml-auto routes" navbar>
<NavItem>
<Link to="/" onClick={this.closeNavbar}>Posts</Link>
</NavItem>
<NavItem>
<Link to="/posts/new" onClick={this.closeNavbar}>New Post</Link>
</NavItem>
</Nav>
</Collapse>
</Navbar>
</section>
</div>
);
}
}
export default Topbar;
It also handles outside clicks.
FontAwesomeLibrary
import { library } from '#fortawesome/fontawesome-svg-core';
import { faCoffee } from '#fortawesome/free-solid-svg-icons';
import { faMugHot } from '#fortawesome/free-solid-svg-icons';
import { faTimes } from '#fortawesome/free-solid-svg-icons';
import { faBars } from '#fortawesome/free-solid-svg-icons';
import { faChevronUp } from '#fortawesome/free-solid-svg-icons';
library.add(faCoffee);
library.add(faMugHot);
library.add(faTimes);
library.add(faBars);
library.add(faChevronUp);
export default library;
I created FontAwesomeLibrary according to
https://fontawesome.com/how-to-use/on-the-web/using-with/react
This is an issue with routing. On a normal webpage a link in a bootstrap nav would cause a new page to load with the nav now closed. Since react doesn't reload the page the nav remains open. In order to fix this you'll need to add the following to each of your <Link> elements in the nav: onClick={this.toggleNavbar}.
I am showing loading gif, until canvas is fully rendered, i make then callback to set visible of loading gif to off. But all time during rendering, gif rotating is stopped and other parts of page doesn't react too. So is there any way ho to render any component asynchronous to prevent influencing with other parts of page?
class GraphPage extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false,
print: null,
loading: true
}
}
componentDidMount(){
this.setReady();
}
render(){
const graphList = graphStore.getGraphValue();
var {data} = this.props;
return(
<div>
<div className="inputs">
<Inputs modal={false} unit='%' list={graphList.rotation} descTitle={data.graph.machine}/>
<Inputs modal={false} unit='mm' list={graphList.machine} descTitle={data.graph.rotation}/>
</div>
<div className="graph">
{this.state.loading? <img src={loadingIcon}/> : false}
{this.state.print? <Print readyToRender={this.update.bind(this)}/> : false}
</div>
</div>
)
}
update(){
this.setState({
loading: false
})
}
setReady(){
setTimeout(function() {
this.setState({print: new Print()})
}.bind(this), 1000);
}
}
I would put the rotating gif in the renderer of Print.
class Print extends React.Component {
constructor(props) {
super(props);
this.state = {
renderFinished: true
}
this.calculate().then(function() {
/* Canvas done => display it! */
this.setState({ renderFinished: true })
}.bind(this))
calculate() {
var result = new Promise();
// Something asyncronous, just an example
setTimeout(function(){
while(doCalc) {
if(calcIsDone) {
// Ready for render
result.resolve(theResult);
}
}
}.bind(this), 0);
return result;
}
render() {
return {
renderFinished ?
<div>
{ /* Here goes the rendered canvas output */ }
</div>
:
<img src={loadingIcon}/>
}
};
}
And then GraphPage looks like this
class GraphPage extends React.Component {
constructor(props) {
super(props);
}
render(){
// It look like graphStore is globally available so Print also can access it directly
const graphList = graphStore.getGraphValue();
var {data} = this.props;
return(
<div>
<div className="inputs">
<Inputs modal={false} unit='%' list={graphList.rotation} descTitle={data.graph.machine}/>
<Inputs modal={false} unit='mm' list={graphList.machine} descTitle={data.graph.rotation}/>
</div>
<div className="graph">
{ /* Maybe graphStore should be given here as a prop? */ }
<Print/>
</div>
</div>
)
}
}