How to tigger onClick function of another component element - javascript

I created one class base component and one functional component. There are three buttons inside the functional component and I called that component to my class based component.
The functional component:
function PanelButton(props){
return (
<div>
<Button.Ripple
color="success"
type="submit"
style={{margin:"5px", width:"110px"}}
>
Submit
</Button.Ripple>
<Button.Ripple
color="primary"
id="clearButton"
type="button"
style={{margin:"5px", width:"110px"}}
>
Clear
</Button.Ripple>
<Button.Ripple color="danger" type="button" style={{margin:"5px", width:"110px"}}>
Close
</Button.Ripple>
</div>
)
}
export default PanelButton;
The class base component, in which I imported the functional component into:
import PanelButton from '../../components/customzied/PanelButton';
class TicketNew extends React.Component{
state = {
alertOption:[],
}
clickClear = () => {
console.log("ok");
}
render() {
const rqst = this.state.rquirdSate;
return (
<Card>
<Formik>
{ ({ errors, touched}) => (
<div>
<Form onSubmit={handleSubmit}>
<CardHeader>
<PanelButton />
</CardHeader>
<CardBody>
<Row />
</CardBody>
</Form>
</div>
)}
</Formik>
</Card>
)
}
}
export default TicketNew;
When I click the button(id = "clearButton") from functional component, I need to run the Click clear function in Class component.

You can pass onClick callback handlers as props to PanelButton to attach to each button's onClick prop. Pass clickClear as callback for clear button.
PanelButton
function PanelButton(props) {
return (
<div>
...
<Button.Ripple
color="primary"
id="clearButton"
type="button"
style={{ margin: "5px", width: "110px" }}
onClick={props.onClear} // <-- attach callback to button's onClick handler
>
Clear
</Button.Ripple>
...
</div>
);
}
TicketNew
class TicketNew extends React.Component {
state = {
alertOption: []
};
clickClear = () => {
console.log("ok");
};
render() {
const rqst = this.state.rquirdSate;
return (
<Card>
<Formik>
{({ errors, touched }) => (
<div>
<Form onSubmit={handleSubmit}>
<CardHeader>
<PanelButton onClear={this.clickClear}/> // <-- pass this.clickClear to onClear prop
</CardHeader>
<CardBody>
<Row></Row>
</CardBody>
</Form>
</div>
)}
</Formik>
</Card>
);
}
}

You can pass the clickClear function as props to the PanelButton component. The PanelButton code will look like the following,
function PanelButton(props){
return(
<div>
<Button.Ripple color="success" type="submit" style={{margin:"5px", width:"110px"}}>
Submit
</Button.Ripple>
<Button.Ripple color="primary" id="clearButton" onClick={props.onClickCallback} type="button" style={{margin:"5px", width:"110px"}}>
Clear
</Button.Ripple>
<Button.Ripple color="danger" type="button" style={{margin:"5px", width:"110px"}}>
Close
</Button.Ripple>
</div>
)
}
And the TicketNew code will look like this,
...
<CardHeader>
<PanelButton onClickCallback={this.clickClear.bind(this)} />
</CardHeader>
...

Related

How to implement conditional rendering in React Reusable Component?

I have this reusable component where I would like to pass a value through that if true: a button is returned and if the value is false: the button doesn't render. I can't figure out how to do this using reusable components. The boolean variable I want to use is displayButton where if it is true, then the button is rendered and if it is false then the button is not rendered.
const Test = ({ name, value, onClick, purchased, displayButton }) => {
return (
<div class="cardData">
<h5>{name}</h5>
<p>Cost: {value}</p>
//if display button = true, display this button, if false, button is not displayed
<button
type="button"
onClick={onClick}
class="btn btn-primary"
value={value}
name={name}
>
Purchase
</button>
<h4>{purchased}</h4>
</div>
);
};
export default Test;
Any help would very appreciated!
const Test = ({ name, value, onClick, purchased, displayButton }) => {
return (
<div class="cardData">
<h5>{name}</h5>
<p>Cost: {value}</p>
{displayButton &&
<button
type="button"
onClick={onClick}
class="btn btn-primary"
value={value}
name={name}
>
Purchase
</button>
}
<h4>{purchased}</h4>
</div>
);
};
export default Test;
if displayButton has the value of true it will render the button otherwise not
This will work.
const Test = ({ name, value, onClick, purchased, displayButton }) => {
return (
<div class="cardData">
<h5>{name}</h5>
<p>Cost: {value}</p>
{ displayButton &&
<button
type="button"
onClick={onClick}
class="btn btn-primary"
value={value}
name={name}
>
Purchase
</button>
}
<h4>{purchased}</h4>
</div>
);
};
export default Test;
You can create a ShowHide component which can be utilized for conditional-rendering instead of having logical operators in every JSX where you need to conditionally render.
// create a ShowHide component
const ShowHide = ({show,children} ) => show && children
// your Test component with the button wrapped in ShowHide
const Test = ({ name, value, onClick, purchased, displayButton }) => {
return (
<div class="cardData card col-6 m-3">
<h5>{name}</h5>
<p>Cost: {value}</p>
<ShowHide show={displayButton}>
<button
type="button"
onClick={onClick}
class="btn btn-primary"
value={value}
name={name}
>
Purchase
</button>
</ShowHide>
<h4>{purchased}</h4>
</div>
);
};
const root = document.getElementById('root');
ReactDOM.render(
<Test name="My Card"
value="250,000"
onClick={() => alert('clicked')}
purchased="Yes!"
displayButton={false}
/>,
root
)
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Good Luck...

Toggle CSS style in a function React component

Every post or tutorial on how to toggle css in React assumes that I'm using a class component. However, I'm using a function component and don't have access to this and state. Can somebody tell me how to toggle a CSS style for a JSX element in a React function component?
import React from 'react';
import { Row, Container, Col } from 'react-bootstrap';
const FilterBar = ( {eventFilters, setEventFilters} ) => {
const someFunction = () => {
// code in here
}
return(
<div className="row-fluid" >
<Container fluid >
<Row className="justify-content-md-center mb-2 mt-2">
<Col onClick={someFunction}> <button value="ALL"> All </button> </Col>
<Col onClick={someFunction}> <button value="WORKSHOP"> Workshop </button> </Col>
<Col onClick={someFunction}> <button value="MINIEVENT"> Minievent </button> </Col>
</Row>
<Row className="justify-content-md-center mb-2">
<Col onClick={someFunction}> <button value="SPEAKER"> Speaker </button></Col>
<Col onClick={someFunction}> <button value="MEAL"> Meal </button> </Col>
<Col onClick={someFunction}> <button value="OTHER"> Other </button> </Col>
</Row>
</Container>
</div>
);
}
export default FilterBar;
Toggling some style via click event object. You can use the event target style property to change the current textDecoration property to "line-through" or nothing ("").
const toggleStrikethrough = (e) => {
e.target.style.textDecoration =
e.target.style.textDecoration === "line-through" ? "" : "line-through";
};
function App() {
const toggleStrikethrough = (e) => {
e.target.style.textDecoration =
e.target.style.textDecoration === "line-through" ? "" : "line-through";
};
return (
<div className="App">
<div onClick={toggleStrikethrough}>ALL</div>
<div onClick={toggleStrikethrough}>WORKSHOP</div>
<div onClick={toggleStrikethrough}>MINIEVENT</div>
<div onClick={toggleStrikethrough}>SPEAKER</div>
<div onClick={toggleStrikethrough}>MEAL</div>
<div onClick={toggleStrikethrough}>OTHER</div>
</div>
);
}
Note: This is generally frowned upon though and considered an anti-pattern as you are directly manipulating the DOM. The better and more react way is to maintain a toggled "state" in local component state for each element you want to toggle style (or anything really) of.

How to pass data from a table row and pass it to another component when it renders?

I have a component that shows a table and one of its columns have a field Actions which has buttons (view, edit, delete etc.). On button click, I need to render another component (component is a popup) and pass the data from the table so that it displays the data in some form which I need to further add.
I have managed to get the current data from its row by passing in onClick. I tried to use state for another component to render but it didn't work out. I'm using Semantic-UI React components to display the button with animations.
Here is the code that has the table,
const MainContent = () => {
const [actions, setActions] = useState(false);
const handleView = (rowData) => {
console.log(rowData);
setActions(true);
if (actions == true) return <ParentView />;
};
....
....
const contents = (item, index) => {
return item.routeChildEntry ? (
<>
<tr key={index}>
<td>{item.appName}</td>
<td></td>
<td>{item.createdTs}</td>
<td>{item.pattern}</td>
<td></td>
<td></td>
<td></td>
<td>
<Button animated onClick={() => handleView(item)}>
<Button.Content visible>View</Button.Content>
<Button.Content hidden>
<Icon name="eye" />
</Button.Content>
</Button>
</td>
</tr>
{item.routeChildEntry.map(routeContents)}
</>
) : (
....
....
....
);
};
return (
<div>
....
{loading ? (
<div className="table-responsive">
<table className="table">
<thead>
<tr>
<th>AppName</th>
<th>Parent_App</th>
<th>Created_Date</th>
<th>Req_Path</th>
<th>Resp_Code</th>
<th>Resp_Content_Type</th>
<th>Resp_Delay</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{data.map((routes, index) => {
return routes.map(contents, index);
})}
</tbody>
</table>
</div>
) : (
....
....
)}
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default MainContent;
Below is the component to render on button click,
import React from "react";
import Popup from "reactjs-popup";
import { Icon } from "semantic-ui-react";
const Parent = (props) => {
return (
<Popup trigger={<Icon link name="eye" />} modal closeOnDocumentClick>
<h4>in parent</h4>
</Popup>
);
};
export default Parent;
How can I render the other component and pass data to it on button click?
Data can be passed to other components as props.
For example, if your component is <ParentView />, and the data you are passing is contained in the variable rowData, you can pass it as:
<ParentView dataPassedByAkhil = {rowData}/>
Then in your ParentView component,
export default function ParentView({dataPassedByAkhil}) {
console.log(dataPassedByAkhil);
Alternatively, you can accept the data as props as below
export default function ParentView(props) {
console.log(props.dataPassedByAkhil);
If you want to open and close another popup, you can pass a state just like above.
<PopupComponent open={stateSetForPopupByParent}/>
Example of popup using state.
Updated link above with how to pass data to the dialog from rows of buttons
Here is the full code:
export default function FormDialog() {
const [open, setOpen] = React.useState(false);
const [valueofRow, setValueOfRow] = React.useState();
const handleClickOpen = (value) => {
setValueOfRow(value);
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button
variant="outlined"
color="primary"
onClick={() => {
handleClickOpen("John");
}}
>
Row 1 - value is John
</Button>
<br />
<br />
<Button
variant="outlined"
color="primary"
onClick={() => {
handleClickOpen("Sally");
}}
>
Row 2 Value is Sally
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="edit-apartment"
>
<DialogTitle id="edit-apartment">Edit</DialogTitle>
<DialogContent>
<DialogContentText>Dialog fired using state</DialogContentText>
<h1>{valueofRow} was clicked and passed from the row</h1>
<TextField
autoFocus
margin="dense"
id="field"
label="some field"
type="text"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="secondary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Submit
</Button>
</DialogActions>
</Dialog>
</div>
);
}

How to replace one React Component with another OnClick?

I have a "sign up" button. When it is clicked, I would like for it to render a new component, called "SignUp". I would like for the new component to replace the "sign up" button.
Currently, I am using setState so that when the button is clicked, a new component is rendered. However, the button is not being replaced, the "SignUp" component is just rendered beside the button. What may be a good approach for me to replace the button with the new component being rendered?
I have provided my code below:
export default class SignUpSignIn extends Component {
constructor() {
super();
this.state = {
clicked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
clicked: true
});
}
render () {
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
<div onClick={this.handleClick}>
{this.state.clicked ? <SignUp /> : null}
<Button id="SignUpButton" color="primary"> Sign Up </Button>
</div>
</Col>
</div>
)
}
}
Well, you're not rendering both components conditionally, only the SignUp. Instead of having null in your ternary, render the sign in button when state.clicked === false:
render () {
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
{this.state.clicked ? (
<SignUp />
) : (
<Button id="SignUpButton" color="primary" onClick={this.handleClick}> Sign Up </Button>
)}
</Col>
</div>
)
}
one way to do it is like this , i didnt test it yet but it should work
render () {
let show = <div></div>
if(this.state.clicked){
show = <SignUp />
}
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
{show}
<Button id="SignUpButton" color="primary" onClick={this.handleClick}> Sign Up </Button>
</Col>
</div>
)
}

React-Redux: Passing Event Handling inside map function

New to React/Redux, I am having hard time implementing on event handling.
I know that the 'this' reference key goes null when passed into the map (this.props.addRecipe.map of recipebox) function but I don't how to resolve it.
Essentially I would like to pass the onChange handler to ModalBox for each element in the array.
src/containers/recipebox
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ListGroup, ListGroupItem, Panel, Button, Modals } from 'react-bootstrap';
import MyModal from '../components/mymodal';
import { bindActionCreators } from 'redux';
import { deleteRecipe } from '../actions/index';
import shortid from 'shortid'
import ModalBox from '../containers/modalbox'
class RecipeBox extends Component {
constructor(props){
super(props);
this.renderRecipeList = this.renderRecipeList.bind(this)
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
renderRecipeList(recipeItem, index){
const recipe = recipeItem.recipe;
const ingredients = recipeItem.ingredients;
const id = shortid.generate();
return(
<div key={id}>
<Panel bsStyle="primary" collapsible header={<h3>{recipe}</h3>}>
<ListGroup >
<ListGroupItem header="Ingredients"></ListGroupItem>
{ingredients.map(function(ingredient,index){
return <ListGroupItem key={index}>{ingredient}</ListGroupItem>;
})}
<ListGroupItem>
<Button
onClick={() => this.props.deleteRecipe(recipeItem)}
bsStyle="danger">Delete
</Button>
<ModalBox
modalTextTitle={'Edit Recipe'}
recipeName={recipe}
userIngredients={ingredients}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
onClickSubmit={this.onClickSubmit}
/>
</ListGroupItem>
</ListGroup>
</Panel>
</div>
)
}
render(){
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(this.renderRecipeList)}
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
addRecipe : state.recipeState
};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({deleteRecipe : deleteRecipe}, dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeBox);
src/containers/modalbox
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
class ModalBox extends Component {
constructor(props){
super(props)
this.state = {
showModal: false
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal(){
this.setState({
showModal: !this.state.showModal
});
}
submitData(link){
link()
this.toggleModal()
}
render() {
return (
<div>
<Button
bsStyle="info"
onClick={this.toggleModal}
>
{this.props.modalTextTitle}
</Button>
<Modal show={this.state.showModal} onHide={this.toggleModal}>
<Modal.Header closeButton>
<Modal.Title>{this.props.modalTextTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.props.recipeName}
onChange= {this.props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
value={this.props.userIngredients}
onChange={this.props.handleUserIngredientsChange}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={ () => this.submitData(this.props.onClickSubmit) }>
{this.props.modalTextTitle}
</Button>
<Button
bsStyle="danger"
onClick= {this.toggleModal}
>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default ModalBox
inside map function you need to change the this like below code,
render(){
const self = this;
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(self.renderRecipeList)}
</div>
</div>
)
}

Categories