React set draggable antd modal - javascript

I'm trying to add a antd modal with drag&drop features.
import React, { Component } from "react";
import Draggable from "react-draggable";
import { Modal } from 'antd';
import 'antd/dist/antd.css';
export default class App extends Component {
state = {
disabled: false
};
render = () => {
const { disabled } = this.state;
return (
<div className="container">
<Modal visible>
<Draggable>
<div>
<h4 style={{ height: 20, userSelect: "none" }}>
{"Drag Me"}
</h4>
<textarea disabled={!disabled} className="uk-textarea" />
<br />
</div>
</Draggable>
</Modal>
</div>
);
};
}
Here's my sanbox code https://codesandbox.io/s/small-currying-j3emq, but it seems that react-draggable in ant modal element doesn't work, probably if I can set the element "ant-modal-content" as draggable element this works.
Does anyone know if it is possible to put the draggable element via props in react-draggable?
I am also available to change the package for drag & drop, I just need to be able to drag a antd modal

Just place your <Draggable> inside your <Modal> and not the opposite
return (
<div className="container">
<Modal visible>
<Draggable>
<div>
<h4 style={{ height: 20, userSelect: "none" }}>{"Drag Me"}</h4>
<textarea disabled={!disabled} className="uk-textarea" />
<br />
</div>
</Draggable>
</Modal>
</div>
);

Related

How do you style custom data grid toolbar items?

I have this toolbar with 2 custom buttons and 3 imported material data grid toolbar components, I want them to match but preferably apply the material styles to my custom components yet I can't find a style import for them anywhere in their docs. But anyway I can get them to match would be huge. Does anyone have some advice?
const Toolbar = () => {
return (
<GridToolbarContainer>
<div
className={classes.toolbar}
onClick={() => {
toggleSearch();
}}
>
<SearchIcon />
<p>SEARCH</p>
</div>
<div
className={classes.toolbar}
onClick={() => {
bookmarkCases(selectedRows);
}}
>
<BookmarkBorderIcon />
<p>SAVE CASES</p>
</div>
<GridColumnsToolbarButton />
<GridDensitySelector />
<GridToolbarExport />
</GridToolbarContainer>
);
};
Instead of making an icon button out of a <div>, why not use the startIcon prop in an MUI <Button />, e.g.
From this:
<div
className={classes.toolbar}
onClick={() => {toggleSearch()}}
>
<SearchIcon />
<p>SEARCH</p>
</div>
to this:
<Button
className={classes.toolbar}
onClick={() => {toggleSearch()}}
startIcon={<SearchIcon />}
>Search
</Button>
All the styles should match because MUI DataGrid toolbar buttons are just MUI Buttons
After a bit of a struggle I found a solution. I was able to achieve a consistent style for all toolbar buttons by passing the styles through the DataGrid itself.
export const StyledDataDrid = styled(DataGridPremium)<DataGridPremiumProps>(({ theme }) => ({
'& .MuiDataGrid-toolbarContainer': {
'& .MuiButton-text': {
fontSize: '16px !important',
color: '#074682',
},
'& .MuiBadge-badge': {
backgroundColor: '#074682',
},
},
}));
Or you can style it on the DataGrid component using the sx property as explained in this issue: https://github.com/mui/mui-x/issues/3686#issuecomment-1018469717

Why does a useCallback option have to be called with a class component in Reactjs?

I am stumped. I have been trying to get a simple cleartext button to work. I have tried all the option available on this platform but nothing is working for me. React Hook useCallback cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook. I have no idea why this error is occurring. I am pretty new to react can anyone please help? I am trying to clear the text on a click of the clear button.
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: ""
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
const handleClick = useCallback(() => {
e.target.value = '';
}, []);
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={handleClick}> Click to clear</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;
It is because you try to use hooks in a class based component. You can only use hooks like useCallback in functional components. Therefore you are mixing the concepts of object oriented and functional programming.
The following should do the trick:
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: ""
};
const handleClick = (e) => {
e.target.value = '';
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={this.handleClick}> Click to clear</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;
useCallback hooks can only be used in functional components OR in a custom Hook NOT in class components.
You have declared your App component in class based approach i.e. Object oriented approach. To use useCallback hook for this, you should change your App component declaration to a functional component or Custom hook.
Something like this
function App() {
return (
<>Hello World!</>
);
}
you cannot useCallBack hook in class Component,we can do a simple thing to clear the button text, by using
a button text state, i.e. { btnTxt: "Clear ButtonText"} than update the state onclick
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: "",
btnTxt: "Clear ButtonText"
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={()=> this.setState({btnText:""})}> {this.state.btnTExt}</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;

How to position Dialog to top in Material-UI

I am currently creating a popup dialog. However, my dialog is positioned popping up in the center.
How do I make the position at the very top of the page when I press the popup btn?
Here is my code
<div>
<div id="so_reg" className="buy_btn" onClick={this.onClickCashBuy.bind(this)}>
Pop up button
</div>
<Dialog className="dialog" modal={false} open={this.state.buy_cash_popup} onRequestClose={this.onClickBuyCashCancel} style={{color: 'green'}} >
<Test product={{price: this.state.buy_cash_type}} />
</Dialog>
</div>
You can override the style of scrollPaper in <Dialog />
Functional component
const useStyles = makeStyles({
scrollPaper: {
alignItems: 'baseline' // default center
}
});
const classes = useStyles();
Classical component
const styles = theme => createStyles({
scrollPaper: {
alignItems: 'baseline' // default center
}
});
const { classes } = props;
export default withStyles(styles)(YourComponent);
Usage
<Dialog classes={{scrollPaper: classes.scrollPaper }}>
Refer: document of Material-UI Dialog CSS API
The HTML structure of Dialog which we can see from dev tools
Choose the MuiDialog-scrollPaper from below
<div
class="MuiDialog-container MuiDialog-scrollPaper makeStyles-dialog-163"
role="none presentation"
tabindex="-1"
style="opacity: 1; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;"
>
<div
class="MuiPaper-root MuiDialog-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm MuiPaper-elevation24 MuiPaper-rounded"
role="dialog"
aria-labelledby="simple-dialog-title"
>
...
</div>
</div>
In your code
import { withStyles } from '#material-ui/styles';
const styles = theme => createStyles({ // change to this
scrollPaper: {
alignItems: 'baseline'
}
});
class Shop extends Component {
render(){
const { classes } = this.props; // add this
return(
<Dialog className="dialog" classes={{scrollPaper: classes.scrollPaper }} modal={false} open={this.state.buy_cash_popup} onRequestClose={this.onClickBuyCashCancel} style={{color: 'green'}} >
<Test product={{price: this.state.buy_cash_type}} />
</Dialog>
export default withStyles(styles)(Shop); // `styles` here rather than `class`

How can I get this React Bootstrap Modal Working properly?

I have a exercise I am working on/attempting to replicate and I am trying to add a modal button to the file. I have the button and the modal from React Bootstrap, however, I am unable to get the actual modal to show up. I was using the documentation from React-Bootstrap but getting the actual modal to come up is not working, I have tried to import the various modals but to no avail, am I missing something in my code?
import React from 'react';
import { Modal, Form, FormControl, Button, ButtonToolbar, InputGroup } from 'react-bootstrap';
import { connect } from 'react-redux';
import { addItem } from '../actions/itemActions';
function ItemModal(props) {
return (
<div>
<Button
variant="dark"
style={{marginBottom: '2em'}}
>Add Item
</Button>
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Add to Shopping List
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Label for="item">Item</Form.Label>
<InputGroup className="mb-3">
<FormControl
type="text"
name="name"
id="item"
aria-label="Add Shopping Item"
aria-describedby="basic-addon2"
/>
<InputGroup.Append>
<Button onClick={props.onHide} variant="outline-dark">Add</Button>
</InputGroup.Append>
</InputGroup>
</Form>
</Modal.Body>
</Modal>
</div>
);
}
function App() {
const [modalShow, setModalShow] = React.useState(false);
return (
<ButtonToolbar>
<Button variant="dark" onClick={() => setModalShow(true)}>
Add Item
</Button>
<ItemModal
show={modalShow}
onHide={() => setModalShow(false)}
/>
</ButtonToolbar>
);
}
export default connect()(ItemModal);
I do have this extra bit of code that I though would function to open the modal but I don't think it works with this version of Bootstrap?
state = {
modal: false,
name: ''
}
toggle = () => {
this.setState({
modal: !this.state.modal
});
};
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
From your code snippet, I found an issue.
You have 2 component's in a single file, App and ItemModal. From which App component is your base / parent component and ItemModal is your child component.
But you are exporting child compoennt,
export default connect()(ItemModal);
You should export the parent component,
export default connect()(App);

Rebass modal not showing when state is changed. Why is it not passing true?

The modal is not showing even though I passed a boolean of true attribute to function. It seems that SuccessModal turns true but Overlay does not.
How come it's not working?
import React, {PropTypes} from 'react';
import {
Overlay,
Panel,
PanelHeader,
PanelFooter,
Button,
Text,
//Close,
Space
} from 'rebass';
function SuccessModal ({modalOpen}) {
return (
<Overlay
open={modalOpen}
>
<Panel theme="success">
<PanelHeader>
Wicckkkeedd!
<Space auto />
/>
</PanelHeader>
<img
src='http://lorempixel.com/512/384/cats'
style={{
maxWidth: '100%',
height: 'auto'
}} />
<Text>
<b>Panel:</b> Something laid as a covering something else
</Text>
<PanelFooter>
<Space auto />
<Button
theme='success'
children='Meow!'
/>
</PanelFooter>
</Panel>
</Overlay>
);
}
export default SuccessModal;
If you need more code to debug please let me know!
Thanks in advance.
This works by accessing props children.
import React, {PropTypes} from 'react';
import {
Overlay,
Panel,
PanelHeader,
PanelFooter,
Button,
Text,
//Close,
Space
} from 'rebass';
function SuccessModal ({modalOpen}) {
return (
<Overlay
open={modalOpen.open}
>
<Panel theme="success">
<PanelHeader>
Wicckkkeedd!
<Space auto />
/>
</PanelHeader>
<img
src='http://lorempixel.com/512/384/cats'
style={{
maxWidth: '100%',
height: 'auto'
}} />
<Text>
<b>Panel:</b> Something laid as a covering something else
</Text>
<PanelFooter>
<Space auto />
<Button
theme='success'
children='Meow!'
/>
</PanelFooter>
</Panel>
</Overlay>
);
}
export default SuccessModal;

Categories