How can I reduce the number of buttons? - reactjs

I need to have only one button doing two things one by one. I have two buttons "Обучить" and "Генерировать" and they both do something onClick. Is it possible to do it all with one button?
<Button
variant="contained"
color="primary"
style={{
background:
"linear-gradient(45deg, #00ACD3 30%, #00BE68 90%)"
}}
onClick={this.parseInput}
>
Обучить
</Button>
<Button
variant="contained"
color="primary"
style={{
background:
"linear-gradient(45deg, #00ACD3 30%, #00BE68 90%)"
}}
onClick={() => {
this.props.updateData(this.state.filterArray);
}}
>
Генерировать
</Button>

Of course you can. You can use a variable to decide what action you want to perform on onClick function
onClick={() => {
if(this.props.type == 'update')
this.props.updateData(this.state.filterArray);
else
this.parseInput()
}}
You can use same property type (or anything you like) to render different labels
{{this.props.type=='update'? 'Генерировать': 'Обучить'}}

I assume that you want to make a component reusable? In that case you might want to design your component like so.
const NewButton = ({onClick, children}) => (
<Button
variant="contained"
color="primary"
style={{
background: "linear-gradient(45deg, #00ACD3 30%, #00BE68)
}}
onClick={onClick}>
children
</Button>);
Then your above snip becomes
<NewButton onClick={someFunction}>Something</NewButton>
<NewButton onClick={otherFunction}>Something</NewButton>
This is the basic idea behind any component-based front-end framework and I suggest you go to the react tutorials to learn more.
Otherwise, there are plenty of good articles about the topic out there

If I understand you correctly, you want to use the same component but make them do different things, on click for example.
Here is an example of how you can do it.
import React from 'react';
const Button = ({onClick}) => {
return (
<button
onClick={onClick}
>
Click on me
</button>
)
}
export default Button;
So when you want to pass down a method to the button, you can do it like this.
import Button from './button';
clickerTicker() {
alert("First method, clickerticker");
}
secondaryClick() {
alert("Second method yo");
}
render() {
return (
<div>
<ButtonComponent onClick={this.clickerTicker.bind(this)}/>
<br/>
<ButtonComponent onClick={this.secondaryClick.bind(this)}/>
</div>
);
}
Just pass the onClick to the component

Related

Screen turns black while using antd modal

I have a list of rows in a table. This only happens when i have more rows in a table. I am using modal of antd.
This is my code:
import {Modal,Button} from "antd";
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
const handleOk = (id) => {
store.dispatch(deleteProductList(id));
setIsDeleteModalVisible(false);
};
const handleCancel = () => {
setIsDeleteModalVisible(false);
};
<Button
icon={<DeleteFilled />}
style={{
backgroundColor: "#D15B47",
color: "#ffffff",
}}
onClick={showDeleteModal}
>
Delete
</Button>
<Modal
title="Confirm Delete"
visible={isDeleteModalVisible}
onOk={() => handleOk(record.id)}
onCancel={handleCancel}
>
<p>Are you sure you want to delete this vehicle?</p>
</Modal>
Not much to go on from the content in the question. But I assume that the backdrop has full opacity or a color that has an alpha of 1? Try to inspect the backdrop and see if the color is correct.

Fix date picker inside modal window in react js

I have this component:
const App = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const showModal = () => {
setIsModalVisible(true);
};
const handleOk = () => {
setIsModalVisible(false);
};
const handleCancel = () => {
setIsModalVisible(false);
};
return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
<DatePicker
onChange={test}
open={true}
showNow={false}
dateRender={(current) => {
const style = {};
if (arr.includes(current)) {
style.border = "1px solid red";
style.borderRadius = "50%";
}
return (
<div className="ant-picker-cell-inner" style={style}>
{current.date()}
</div>
);
}}
/>
</Modal>
</>
);
};
When i open the modal i get the calendar outside it. How to put the calendar inside the modal window, not outside like now?
demo: https://codesandbox.io/s/basic-antd494-forked-6lkqg?file=/index.js:269-1303
This is, IMO, incredibly hackish, but was the only way I could get the date picker's popup to behave a bit more nicely nested in a modal.
Use the getPopupContainer prop to specify what the parent should be, it defaults to "body". We can create our own element to append the date popup to.
Use the popupStyle prop to override and set the position CSS rule. It is position: absolute by default, we wan't relative positioning.
Add an empty div after DatePicker for the popup to attach to.
HACK ALERT: DatePicker inserts a div between the one we created and the popup, so CSS rule cascading & inheritance gets fubar'd, it has position: absolute as well. We need to override this to also use relative positioning.
Code:
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
<DatePicker
getPopupContainer={() => document.getElementById("date-popup")}
popupStyle={{
position: "relative"
}}
onChange={test}
open={true}
showNow={false}
dateRender={(current) => {
const style = {};
if (arr.includes(current)) {
style.border = "1px solid red";
style.borderRadius = "50%";
}
return (
<div className="ant-picker-cell-inner" style={style}>
{current.date()}
</div>
);
}}
/>
<div id="date-popup" />
</Modal>
</>
CSS
#date-popup > div {
position: relative !important;
}
The main reason this is hackish is because the use of !important should generally be avoided and instead you should strive to increase a selector's specificity. I was unable to bump it enough to override the style. (I believe this is because that div is also using some inline style prop/attribute)
DatePicker itself is also a kind of Modal so it can't be embedded inside Modal. You can simply check this by inspecting both Modal and DatePicker components.
If you want the DatePicker to be opened, you can control the height of modal body. Something like this.
<Modal
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
bodyStyle={{
height: 400
}}
>
Here is another suggestion:
<Modal
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
centered
style={{ minHeight: `500px` }}
>

Checkbox.Group of ant design React couldn't set the default value

I am developing an ant-design based react functional application. While using the Checkbox.Group, I found that I can't set the default value on a dynamically generated list of select boxes. My criteria is, when the custom modal is opened, depending on the loginId(an integer value) passed, the checkbox should be selected by default. If I unselect then it's fine. But on opening modal for the first time, default value should be set. I'm really trying for a long time, don't know what exactly I'm missing. Would be great if you please help.
here is my code,
export const ContactModal = props => {
const loggedInUser = props.loginUserDetail.id > 0 ? [props.loginUserDetail.id] : [];
console.log("loggedInUser= ",loggedInUser);
const title =
props.contactType === contactTypesEnum[1] ? 'Select MMS contact person' : 'Select Industry contact person';
return (
<Modal
title={title}
visible={props.isVisible}
width={'60%'}
afterClose={props.modalClose}
onCancel={props.handleContactModalCancel}
footer={[
<Button key="back" onClick={props.handleContactModalCancel}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={props.contactModalConfirm}>
{/*<Button key="submit" type="primary" onClick={props.inputSubmit}>*/}
Submit
</Button>
]}
>
{/*<Form key={props.contactList}>*/}
<Form>
<div style={{ overflowY: 'scroll' }}>
{/*<Checkbox.Group defaultValue={[defaultValue]} onChange={props.handleCheckedInput}>*/}
<Checkbox.Group defaultValue={loggedInUser} onChange={props.handleCheckedInput}>
<Row style={{ border: '1px solid #009FE3', paddingLeft: '10px' }}>
{props.contactList.map((elem: { fullName: string; id: number }, index: number) => {
return (
<Col key={index} span={8}>
<Form.Item>
<Checkbox value={elem.id}>{elem.fullName}</Checkbox>
</Form.Item>
</Col>
);
})}
</Row>
</Checkbox.Group>
</div>
</Form>
</Modal>
);
};
The props.loginUserDetail, I'm passing looks like,
export interface ContactLogin {
id:number;
fullName:string;
}
and I checked very correctly that the id is getting populated and has non-zero positive value. Strangely if I hardcode defaultValue={[12]} the right checkbox is marked but the variable assignment of defaultValue={[loggedInUser]}
In the ant design specification I found that the defaultValue type should be string so I tried to use,
const loggedInUser = props.loginUserDetail.id > 0 ? props.loginUserDetail.id.toString() : '';
But it is also not working. If variable value is not selectable then defaultValue={[12]} shouldn't work too. BUt hard-coding is working.
THis is how I'm calling the custom modal,
this is how I'm calling the modal ,
<ContactModal
isVisible={modalVisibilty}
//modalClose={modalClose}
contactList={contactList} //this would be number of contact returned
handleContactModalCancel={handleContactModalCancel}
contactModalConfirm={contactModalConfirm}
handleCheckedInput={handleCheckedInput}
//contactListError={contactListError}
contactType={contactType}
loginUserId={contactType === contactTypesEnum[2]?loginUserDetail.id:0}
//loginUserDetail={contactType === contactTypesEnum[2] ?loginUserDetail : {id:0,fullName:''}}
/>
Can anyone please help me out here ? Thanks much !

ReactJS buttons change color on click

I have 3 buttons in reactjs created with Material UI Buttons.
<>
<Button variant="contained">Button 1</Button>
<Button variant="contained">Button 2</Button>
<Button variant="contained">Button3</Button>
</>
How can I make that when clicking on one, it changes it's color (let's say blue) and the other ones reset to Default?
Because React use JSX, you can put javascript in your html component.
We can imagine a single state that manage your buttons.
in your component you create a state containing integer
const [buttonSelected, setButtonselected] = useState(0);
I'm using the react hook syntax, but it also depend on you implementation.
buttonSelected is the current value of the state and setButtonselected is the function that change the state. When you call it, React will rerender your component and change the display .
You can now add a click function on your return
...
<Button variant="contained" onClick={() => setButtonSelected(1)}>Button 1</Button>
<Button variant="contained" onClick={() => setButtonSelected(2)} >Button 2</Button>
<Button variant="contained" onClick={() => setButtonSelected(3)}>Button3 </Button>
...
This will change the value of buttonSelected each time you click a button.
We now need to change the color , for that we will use use makeStyle, but there is other way to do so.
First, create a style element outside of your component.
const useStyles = makeStyles((theme: Theme) =>
createStyles({
selected: {
background: 'blue',
},
default:{
background: 'default',
}
}
),
);
Then call it in your component
const classes = useStyles();
And finally you can set the style that you want depending on the value
...
<Button className={(buttonSelected === 1) ? classes.selected : classes.default} variant.....
<Button className={(buttonSelected === 2) ? classes.selected : classes.default} variant.....
<Button className={(buttonSelected === 3) ? classes.selected : classes.default} variant.....
...
This is a ternary operator, it's the equivalent of
if(buttonSelected === 1){
return classes.selected
} else {
return classes.default
}
And it should work.
You can learn about it in the conditional rendering of react and in the the styling in react
Dont hesitate if you got any questions :)

Material-UI hover effect line offset bug (React)

I have been looking to implement Material-UI in my React ES6 project. As I have been trying things in a sandbox, I noticed a pretty significant styling quirk on the RaisedButton component. When hovering at times there is either a line at the top or bottom of the button where the hover effect doesn't completely overlap the button. The behavior changes when I override the margins. For instance when I have 8px margins the plain button has no line. When I add 6px margins the button has a line at the top. When I have a 4px margin it has a line at the bottom. This behavior changes also when there's different components next to each other in the HTML.
I am using Source Sans instead of Roboto, but switching back to Roboto has the same behavior. Likewise, keeping text-transform as uppercase instead of none has the same behavior.
I have tried wrapping the button in a div and applying margin or padding to that with the same result.
I am on the latest Chrome on Mac OSX 10.11.3.
Thanks in advance for your help.
I am wrapping the button in a custom class to allow consistent style overrides. Here's my wrappers:
Button Wrapper
...
let customTheme = ThemeManager.getMuiTheme(CustomTheme)
customTheme.button.textTransform = 'none'
const styles = {
button: {
margin: 8
}
}
#ThemeDecorator(customTheme)
class Button extends React.Component {
render() {
return (
<div className="c-button" style={{ display: 'inline-block' }}>
<RaisedButton
style={ styles.button }
label={ this.props.label }
onClick={ this.props.onClick }
primary={ this.props.primary }/>
</div>
)
}
}
...
Modal Wrapper
...
render() {
const actions = [
<Button
label="Cancel"
onClick={ this.props.handleClose } />,
<Button
label="Submit"
primary={ true }
onClick={ this.props.handleClose } />
]
return (
<Dialog
title="Dialog With Actions"
actions={ actions }
open={ this.props.open } >
Only actions can close this dialog.
</Dialog>
)
}
...
Plain RaisedButton by itself
...
<ul>
<li>
<h4>Plain Button</h4>
<Button label="Button" onClick={this.handleClick}/>
</li>
</ul>
...
Plain RaisedButton for Modal
...
<li>
<h4>Plain Modal</h4>
<Button label="Modal Dialog" onClick={ this.handleOpen } />
<Modal
open={ this.state.open }
handleClose={ this.handleClose }
handleOpen={ this.handleOpen } />
</li>
...
I'm hovering my mouse over the buttons in these screenshots. The only difference is the override of the margin in the first one to be 8px.

Resources