How to change The style of a reactstrap modal in react? - reactjs

Problem:
I have created A reactstrap Modal and now I want to add a custom styling to it so that I had a class and wrote CSS styling but it does not seem to work. Can someone help me to solve this problem?. This is my code.
import React, { Component } from "react";
import {
Card,
CardText,
Container,
Row,
Col,
Button,
Modal,
ModalHeader,
ModalBody,
ModalFooter
} from "reactstrap";
import "./Dashbord.css";
class YearCard extends Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}
render() {
return (
<Card className="year">
<Container>
<CardText className="year-text">Year</CardText>
</Container>
<div className="year-full-screen" onClick={this.toggle}>
<i className="fas fa-expand-arrows-alt" />
</div>
<Modal
className="modal-dialog"
isOpen={this.state.modal}
fade={false}
toggle={this.toggle}
>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody>My Modal</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>
Do Something
</Button>{" "}
<Button color="secondary" onClick={this.toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
<hr className="horizentel-line" />
</Card>
);
}
}
export default YearCard;
This is my CSS.
.modal-dialog {
width: 100%;
margin-top: 10%;
}
I searched On the Internet to find a Solution to this problem. But I was unable to find any reasonable solution to this problem. If you can help me It would be a great pleasure for me.

These are the props available for reactstrap modal api,
Reference here
<Modal
className: YourCustomClass,
wrapClassName: YourCustomClass,
modalClassName: YourCustomClass,
backdropClassName: YourCustomClass,
contentClassName: YourCustomClass
/>

Just setting the prop modalClassName as modal-dialog would do the trick.
<Modal
modalClassName="modal-dialog"
isOpen={this.state.modal}
fade={false}
toggle={this.toggle}
>
...

This worked for me
<Modal ClassName={`customClass`} />

Related

Unable to focus form element on modal open with react-hook-form

I'm trying to solve a problem that seems quite straight forward. I want to focus a form element as soon as a modal opens.
Since react-hook-form does not provide a direct handle to the form refs, I'm trying to use a useEffect hook and react-hook-forms howngrown setFocus functions but I keep seeing the error:
s.focus is not a function
Code
--> Link to coding sandbox
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import "./styles.css";
import {
ChakraProvider,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
Button,
ModalCloseButton,
useDisclosure
} from "#chakra-ui/react";
export default function App() {
const { setFocus, register } = useForm();
const { isOpen, onClose, onOpen } = useDisclosure();
useEffect(() => {
if (!isOpen) return;
setFocus("name");
}, [setFocus, isOpen]);
return (
<ChakraProvider>
<div className="App">
<Button onClick={onOpen}>Open</Button>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton />
<ModalBody>
<input {...register("name")} />
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div>
</ChakraProvider>
);
}
Maybe setFocus can't run because the modal content (and the input inside) is first unmounted.
An easy solution using setFocus is to make the form as an independant component :
const Form = () => {
const { setFocus, register } = useForm();
useEffect(() => {
setFocus("name");
}, [setFocus]);
return <input {...register("name")} />;
};
and then include it inside the modalBody.
Fixed sandbox link
Read the Chakra documentation there is one prop initialFocusRef, you can pass the ref to the element you want to focus on initially
Chakra provides 2 props for this use case:
initialFocusRef: The ref of the component that receives focus when the modal opens.
finalFocusRef: The ref of the component that receives focus when the modal closes.
import { useEffect, useRef } from "react";
import { useForm } from "react-hook-form";
import "./styles.css";
import {
ChakraProvider,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
Button,
ModalCloseButton,
useDisclosure
} from "#chakra-ui/react";
export default function App() {
const { setFocus, register } = useForm();
const { isOpen, onClose, onOpen } = useDisclosure();
const initialRef = useRef();
useEffect(() => {
//setFocus("name");
}, [setFocus, isOpen]);
return (
<ChakraProvider>
<div className="App">
<Button onClick={onOpen}>Open</Button>
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={initialRef}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton />
<ModalBody>
<input {...register("name")} ref={initialRef} />
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div>
</ChakraProvider>
);
}
UPDATED BASED ON COMMENT
By default, Chkra focus enabled elements if you just add tabIndex to your elements and give order value appropriately then it will get focused. Previously close button was focused by default, now in the below code you will notice I have given tabIndex=2 to the close button and tabIndex=1 to the input element and it is working as expected.
<ChakraProvider>
<div className="App">
<Button onClick={onOpen}>Open</Button>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton tabIndex="2" />
<ModalBody>
<input tabIndex="1" {...register("name")} />
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div>
</ChakraProvider>
If you want to use that using ref then you can check "How to share ref usage?", maybe it will help you.

Can't display bootstrap modal onClick

I have a problem to display the bootstrap modal in my react-website. Here is my code:
import React,{Component} from 'react';
import './restaurant.css';
import {connect} from "react-redux";
import {IoMdArrowBack} from 'react-icons/io';
import './restaurantMenu.css';
import DishDetailModal from "./dishDetailModal";
class RestaurantMenu extends Component{
renderDishes = (dishes)=>{
console.log(dishes);
return dishes.map((item,index)=>{
console.log(item);
{
if (item.isAvailable === true) {
return (
<div key={index} className="dishContainer">
<button className="dishButton" onClick={()=><DishDetailModal/>}>
<text style={{fontWeight: 'bold'}}>{item.name}</text>
<br/>
<text>{item.discription}</text>
<br/>
<text>{item.price} €</text>
</button>
</div>
)
}else{
return(
<div key={index} className="dishContainer">
<text style={{fontWeight: 'bold'}}>{item.dishTitle}</text>
<br/>
<text>{item.dishDescription}</text>
<br/>
<text>{item.dishPrice} €</text>
</div>
)
}
}
})
}
render(){
return(
<div style={{textAlign:'center'}}>
<br/>
<div className="backButtonClass">
<button
className="backButton"
onClick={this.props.showMenuFunction}
>
<IoMdArrowBack size={40}/>
</button>
</div>
<br/>
{this.renderDishes(this.props.requestedData[this.props.restaurantId].dishes)}
</div>
)
}
}
In the renderDishes-function I want to render return all the dishes and wrap each in a button that opens the modal with specific dish-information. My problem is that the modal doesn't show up onClick. Here is the modal-component:
import React,{Component} from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
export default class DishDetailModal extends Component{
constructor(props) {
super(props);
this.state={
show: true
}
}
handleModal = () =>{
this.setState({show: !this.state.show})
};
render(){
return (
<>
<Button variant="primary" onClick={()=>this.handleModal}>
Launch demo modal
</Button>
<Modal show={this.state.show} onHide={()=>this.handleModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={()=>this.handleModal}>
Close
</Button>
<Button variant="primary" onClick={()=>this.handleModal}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}

React Modal Submit Form

I'm trying to print out a simple buttton clicked text whenever the submit button is click on my reactstrap modal and somehow my code doesn't do anything, not sure what I have wrong.
I have attached a picture for better visualisation , I'm using reactstrap Modal.
import React, { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import Button from "./Button";
// NOTICE
// Modal is brought in with it's own trigger, so import the component where you want the trigger to be.
const ModalComponent = (props) => {
const {
buttonText,
title,
actionButtonText,
cancelButtonText,
children,
className,
} = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const alertshow = () => {
alert("button clicked");
};
const closeBtn = (
<button className="close" onClick={toggle}>
×
</button>
);
return (
<div>
<a className="btn_link" onClick={toggle}>
{buttonText}
</a>
<form onSubmit={alertshow}>
<Modal isOpen={modal} toggle={toggle} className={className}>
<ModalHeader className=" border-0" toggle={toggle} close={closeBtn}>
{title}
</ModalHeader>
<ModalBody className="text-left border-0">
<p className="modal-label">Please enter your email address</p>
{children}
</ModalBody>
<ModalFooter className="modal-footer border-0">
<Button className="btn_secondary modal-btn" onClick={toggle}>
{cancelButtonText}
</Button>{" "}
<input
className="btn btn_primary modal-btn"
type="submit"
value={actionButtonText}
/>
</ModalFooter>
</Modal>
</form>
</div>
);
};
export default ModalComponent;
Its happening form should be part of modal not modal should be part of form. This is why its not referencing onSubmit. You need to do this:
<Modal isOpen={modal} toggle={toggle} className={className}>
<form onSubmit={alertshow}>
...rest all content
</Form>
</Modal>
Here is full code:
import React, { useState } from "react";
import "./styles.css";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "reactstrap";
// NOTICE
// Modal is brought in with it's own trigger, so import the component where you want the trigger to be.
const ModalComponent = (props) => {
const {
buttonText,
title,
actionButtonText,
cancelButtonText,
children,
className
} = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const alertshow = () => {
alert("button clicked");
};
const closeBtn = (
<button className="close" onClick={toggle}>
×
</button>
);
return (
<div>
<div onClick={toggle}>{buttonText}</div>
<Modal isOpen={modal} toggle={toggle} className={className}>
<form onSubmit={alertshow}>
<ModalHeader className=" border-0" toggle={toggle} close={closeBtn}>
{title}
</ModalHeader>
<ModalBody className="text-left border-0">
<p className="modal-label">Please enter your email address</p>
{children}
</ModalBody>
<ModalFooter className="modal-footer border-0">
<Button className="btn_secondary modal-btn" onClick={toggle}>
{cancelButtonText}
</Button>{" "}
<input
className="btn btn_primary modal-btn"
type="submit"
value={actionButtonText}
/>
</ModalFooter>
</form>
</Modal>
</div>
);
};
export default function App() {
return (
<div className="App">
<ModalComponent
title="Hello"
cancelButtonText="Cancel"
actionButtonText="Submit"
buttonText="testing"
/>
</div>
);
}
Here is the demo: https://codesandbox.io/s/fervent-bash-51lxe?file=/src/App.js:0-1826
Accepted answer doesn't work when Modal is scrollable.
Here is how to resolve the issue:
<Modal show={ show } onHide={ onClose }
scrollable={ true }
onSubmit={ handleSubmit(onSave) }
dialogAs={ FormWrappedModal }>
<Modal.Header closeButton>
<Modal.Title>some title</Modal.Title>
</Modal.Header>
<Modal.Body>some body</Modal.Body>
<Modal.Footer>some body</Modal.Footer>
</Modal>
We need to introduce custom component FormWrappedModal for that purpose:
const FormWrappedModal = ( props: any)=>{
return (
<form onSubmit={ props.onSubmit }>
<Modal.Dialog { ...props } />
</form>
);
};

How to hide a modal using a function in class components in React

I am working on a React project, In my project I have two components Users and UsersModal.
In Users component Create User button is there when I click that button UsersModal form has to
Appear. So for that I have imported UsersModal component to Users component. Now initially I need
Not to show UsersModal form so please tell me how to write a function to initially close that
Component.
This is Users.js
import React, { Component } from 'react';
import './Users.css';
import { Container, Row, Col, Button } from 'reactstrap';
import UsersModal from '../../Components/UsersModal/UsersModal';
class Users extends Component {
constructor(props) {
super(props)
this.state = {
}
}
render() {
return (
<Container>
<Row>
<Col>
<div className='mt-3'>
<Button outline color="secondary">Create User</Button>
<UsersModal></UsersModal>
</div>
</Col>
</Row>
</Container>
)
}
}
export default Users
This is UsersModal.js
import React, { Component } from 'react';
import './UsersModal.css';
import {
Button,
Col,
Modal,
ModalBody,
ModalFooter,
ModalHeader,
Row,
FormGroup,
Label,
Input,
} from 'reactstrap';
class UsersModal extends Component {
render() {
return (
<Row>
<Col md="6" sm="6" xs="6">
<Modal isOpen={true}
>
<ModalHeader >Create User</ModalHeader>
<ModalBody>
<FormGroup>
<Label for="exampleName">Name</Label>
<Input
type='text'
name='name'
placeholder='Enter Your name'
/>
</FormGroup>
<FormGroup>
<Label for="exampleEmail">Email</Label>
<Input
type='email'
name='email'
placeholder="Enter Your email"
/>
</FormGroup>
</ModalBody>
<ModalFooter>
<Button color="secondary">
Cancel
</Button>
<Button type="submit" color="primary">
Submit
</Button>
</ModalFooter>
</Modal>
</Col>
</Row>
)
}
}
export default UsersModal
In your User component, you need to set a variable which will be used to show and hide the modal -
toggleUserModal function is used to either hide or show the modal, on button click it will show the modal by setting isModalOpen to true, and you can pass this function to UsersModal via onClose props, so that you can close the modal by clicking a button in UsersModal itself.
import React, { Component } from 'react';
import './Users.css';
import { Container, Row, Col, Button } from 'reactstrap';
import UsersModal from '../../Components/UsersModal/UsersModal';
class Users extends Component {
constructor(props) {
super(props)
this.state = {
isModalOpen: false, // initially modal is hidden
}
}
/**
* This will toggle the modal state
* if modal is hidden, it will open the modal
* else is will close the modal
*/
toggleUserModal = ()=>{
this.setState((state)=>{
return{
isModalOpen: !state.isModalOpen
}
})
}
render() {
return (
<Container>
<Row>
<Col>
<div className='mt-3'>
<Button onClick={this.toggleUserModal} outline color="secondary">Create User</Button>
{this.state.isModalOpen ?
<UsersModal
onClose={this.toggleUserModal}
/>
:null}
</div>
</Col>
</Row>
</Container>
)
}
}
export default Users
You can create a boolean attribute inside your User component, like modalOpen, then render it conditionally in the DOM when you set modalOpen to true
import React, { Component } from 'react';
import './Users.css';
import { Container, Row, Col, Button } from 'reactstrap';
import UsersModal from '../../Components/UsersModal/UsersModal';
class Users extends Component {
constructor(props) {
super(props)
this.state = {
modalOpen: false,
}
}
render() {
return (
<Container>
<Row>
<Col>
<div className='mt-3'>
<Button outline color="secondary">Create User</Button>
{modalOpen ? <UsersModal></UsersModal> : ''}
</div>
</Col>
</Row>
</Container>
)
}
}
export default Users
Now your Users component has the power to switch on/off on the modal view. You can do this by calling this.setState({...this.state, modalOpen: true)

onClick Rendering is not happening ReactJs

I am creating a web application with react.js also using react-bootstrap.
What I want to accomplish is when user click on button then modal will appear but that is not happening.
Button code
<div className="rightButtons">
<button name="updateItem" className="btn btn-primary" onClick={() => { this.onUpdateItem(this.props.selectedAppTypeId)}} >Update Item</button>
</div>
function which will be called.
onUpdateItem = (id) => {
return (
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
Any help would be great help. Thanks.
You are returning HTML into your onClick handler, and not into the Component's render method. If you want to show HTML content after an onClick, you need to actually return those HTML elements within the actual render. Try this:
class Component extends React.Component {
state = {
showModal: false
}
renderModal = () => {
return (
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
render() {
return(
<div>
<button onClick={() => this.setState({showModal:true})}> Show </button>
{this.state.showModal && this.renderModal()}
</div>
)
}
}
Edit: You can also export that entire Modal return statement into its own component, and conditionally render the component when the showModal state is true.
const ModalComponent = (props) => {
return(
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
)
}
class ParentComponent extends React.Component {
state = {
showModal: false
}
render(){
return(
<div>
<button onClick={() => this.setState({showModal:true})}>
Show Modal
</button>
{this.state.showModal && <ModalComponent id='0af141random'/>}
</div>
)
}
}
The problem that you have is that you're passing a react function component as an event handler; the return value of the function is a react component, but calling the function by itself won't mount that component in the DOM and display it.
A better way to make this happen might be to place your Modal component in your component hiearchy, and control whether it is shown by using a callback to change the state of a parent component.
Something like this:
class ParentComponent extends React.Component {
showModal() {
this.setState{
modalActive: true;
}
}
render() {
<div>
<Button onClick={showModal}>Show me the modal!</Button>
<Modal active={this.state.modalActive} />
</div>
}
}
const modalComponent = (props) => {
return (<div style={{ display: (props.isActive) ? "block" : "none "}}>
<h1>I'm a modal!</h1>
</div>)
}
I haven't checked, but I'm sure React Bootstrap has its own prop for displaying/hiding modals.
EDIT: Here's a code example from the react bootstrap documentation that shows it in use https://react-bootstrap.github.io/components/modal/#modals-live

Resources