Having multiple buttons call a function in ReactJS - javascript

Sorry if the title is vague. My problem is that I have three button tags, and for each tag I want it to send a unique argument to selectSupplier(). However no matter what button I press selectSupplier() only receives the last value ("ultramar") as an argument.
selectSupplier(supplier){
this.props.Obj.supplier = supplier
}
render() {
//console.log("SUPPLIER", this.props)
return (
<div>
<button onClick={this.showMenu}>
Select Supplier
</button>
{
this.state.showMenu
? (
<div
className="menu"
ref={(element) => {
this.dropdownMenu = element;
}}
>
<button value="Husky" onClick={this.selectSupplier("Husky")}> Husky </button>
<button value="Shell" onClick={this.selectSupplier("Shell")}> Shell </button>
<button value="Ultramar" onClick={this.selectSupplier("Ultramar")}> Ultramar</button>
</div>
)
: (
null
)
}
</div>
);

You can call like this :
this.selectSupplier.bind(this,"Husky");

Related

Passing function and params through react props

I have an dropdown menu with buttons for the dropdown elements and pressing them causes an fucntion call.
`
<div className = "dropdown-container">
<button className = "dropdown-button"> Sort </button>
<div className = "dropdown-content">
<button className = "sort-button" onClick={() => changeFilter(['sort=-Covered_distance'])}> Furthest </button>
<button className = "sort-button" onClick={() => changeFilter(['sort=+Covered_distance'])}> Shortest </button>
<button className = "sort-button" onClick={() => changeFilter(['sort=-Duration'])}> Longest </button>
<button className = "sort-button" onClick={() => changeFilter(['sort=+Duration'])}> Fastest </button>
</div>
</div>
Im trying to clean up my code as I have multiple dropdown menus next to each other with the same principle. I thought about making a react component that has the structure of the dropdown menu but as I have an function call in it I need to pass this through also so like.
<div className = "filters-container">
<Dropdown changeFilter = { () => changeFilter() }/>
</div>
Now this works as it calls the function changeFilter(), but none of the params from the other component gets called with the call so it basically calls only changeFilter(), when I press any of the buttons. How can I get the params with the call?
You must pass the argument in the changeFilter prop.
For example:
<div className="filters-container">
<Dropdown changeFilter={() => changeFilter(['sort=-Covered_distance'])} />
</div>
Here's a working example:
https://codesandbox.io/s/falling-currying-kd0oco?file=/src/App.js
The problem here is that when you pass a function as a prop, you can't change their parameters inside the component, the parameter has to be passed from the parent.
Pass the paramter ['sort=-Covered_distance'] in changeFilter function like this:
<div className = "filters-container">
<Dropdown changeFilter={() => changeFilter(['sort=-Covered_distance'])} />
</div

How to handle click on specific button in loop?

I have created following design:
Here is the react js code:
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => {
<div className="d-flex justify-content-end">
<button
className="info-button"
data-toggle="collapse"
href="#collapseExample"
role="button"
aria-expanded="false"
aria-controls="collapseExample"
// onClick={
// value.betId != null
// ? _this.getBetIdDetails(value.betId)
// : value.childId != null
// ? _this.getBetIdDetails(value.childId)
// : ""
// }
>
</div>
})}
Here I am trying following task
If I click on one button it should expand the box
But if I click on one button all boxes are expanding.
If I call some method on click its getting called infinitely
Can someone help me to correct the code ?
You can call a function on button click. I think it was calling infinitely because you were not passing a reference to the function.
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => (
<div className="d-flex justify-content-end" key={index}>
<button
className="info-button"
data-toggle="collapse"
href="#collapseExample"
role="button"
aria-expanded="false"
aria-controls="collapseExample"
onClick={
value.betId != null
? () => _this.getBetIdDetails(value.betId)
: value.childId != null
? () => _this.getBetIdDetails(value.childId)
: () => {}
}
>
</div>
)
)}
You were also missing the key prop on div
EDIT:
One button is opening all the boxes because they all have the same IDs and controls.
To make the IDs and controls unique, you can do something like this:
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => (
<div className="d-flex justify-content-end" key={index}>
<button
className="info-button"
data-toggle={`collapse${index}`}
href={`#collapseExample${index}`}
role="button"
aria-expanded="false"
aria-controls={`collapseExample${index}`}
onClick={
value.betId != null
? () => _this.getBetIdDetails(value.betId)
: value.childId != null
? () => _this.getBetIdDetails(value.childId)
: () => {}
}
>
</div>
)
)}
The solution seems pretty straightforward. You're directly executing a function in the onClick. That's why all of them are getting executed. You just need to change the onClick as follows:
onClick = { () => {
if(value.betId != null){
_this.getBetIdDetails(value.betId)
} else if (value.childId != null){
_this.getBetIdDetails(value.childId)
} else {return ""} }
To each div you need to give unique id, may be primary key of that row, and when that button is clicked pass the id to the opening function, and append that to id of that div to open. Hope it helps. This will go like this:-
onclick=handler(1)
div id should be like this:- open1, open2
handler should be like this:-
handler(id) => idofelement+id open

Validating a value when button is pressed before passing it

Hi I am new to React and I am a little bit confused on how to validate a value before passing it to the partialRefund function I have.
I am trying to set a simple validation to make sure the value is not empty and numeric before passing it to the partialRefund function.
The first line is the code I currently have. The second line is the code I am trying to write for the validation but it is not working.
Any help would be really appreciated! Thanks!
//Current code
{partialRefundSelected ? <div> <input id={`partial_refund_${order_id}`} type='text'/> <button onClick={() => partialRefund(order_deets_obj,"partialRefund",document.getElementById('partial_refund_'+order_id).value)}> Refund Order </button> </div> : ""}
//Code I am trying to use
{partialRefundSelected ? <div> <input id={`partial_refund_${order_id}`} type='text'/> <button onClick={(validateValue(document.getElementById('partial_refund_'+order_id).value)) => partialRefund(order_deets_obj,"partialRefund",document.getElementById('partial_refund_'+order_id).value)}> Refund Order </button> </div> : ""}
On the second line i am trying to pass a function that will validate the value and the pass it to the partialRefund function. But it doesnt seem to be working :(
Use this:
{
partialRefundSelected ?
<div>
<input id={`partial_refund_${order_id}`} type='text'/>
<button onClick={() => {
const validatedValue=validateValue(document.getElementById('partial_refund_'+order_id).value));
partialRefund(order_deets_obj,"partialRefund",validatedValue);
}}> Refund Order
</button>
</div> :
""}
You can do the validation in the onClick callback if you add curly brackets around the parttialRefund call.
export default function App() {
const partialRefundSelected = true;
const order_id = 1;
const order_deets_obj = { deets: "good deets" };
const partialRefund = (deets, someString, someValue) => {
console.log(deets, someString, someValue);
};
return partialRefundSelected ? (
<div>
<input id={`partial_refund_${order_id}`} type="text" />
<button
onClick={() => {
const value = document.getElementById("partial_refund_" + order_id)
.value;
// Do validation here
if (value === "I LOVE CATS") {
partialRefund(order_deets_obj, "partialRefund", value);
}
}}
>
Refund Order
</button>
</div>
) : (
""
);
}
While this is an option in react, I would suggest making your input a Controlled Component. This would allow you to keep the input's text in state instead of needing to pull the text off of the element after a click. Here is an example.

Disable onClick event with JSON data

I want to disable a button click using a parameter from a JSON file:
JSON Parameter
"reactJson": {
"disable:"true"
}
My current onClick method works fine but if the parameter is true, I want to disable the onClick event. Currently my code looks like this:
let myJsonParam = reactJson.disabled //default is false
onClick
<button
onClick={() => {
handleSumbit();
}}
>
Exit and Save
</button>;
I know I can do this if it were a boolean:
{
!myJsonParam ? (
<button
onClick={() => {
handleSumbit();
}}
>
Exit and Save
</button>
) : (
<button
onClick={() => {
}}
>
Exit and Save
</button>
);
}
But since it is a string in JSON trueis there a different way to disable the button when the string is changed in JSON instead of replicating it and removing the onClick event ?
How do you think of this solution?
<button
onClick={() => {
if (!myJsonParam)
handleSumbit();
}}
>
Exit and Save
</button>

React Typescript - Show hidden Divs not currently showing

I have an array that contains Title1, Title2, Title3, all the way to Title8. If that item is not empty I want to display with it's corresponding information. Currently that works.
However I want to add a button that will allow me to display all fields. For example let's say Title1 through Title3 is not null. It will show that (which it currently does). I want to add a button that when clicked will display all Titles 1-8.
Here is my current code. In the code below I'm only showing 4 if statements and removed all content to save space:
{ this.state.showExtraRows? <div>
{ this.state.Product[0].Title1 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title2 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title3 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title4 ?
<div>
//Display some fields here
</div>
: null
}
</div>
: null
}
<button className={styles.btn}
type="button"
onClick={()=>{this.setState({showExtraRows:!this.state.showExtraRows})}}>
{ this.state.showExtraRows? 'Hide Rows' : 'Show Rows'}
</button>
I'm not too sure if I'm supposed to wrap the whole thing in the this.state.showExtraRows? statement.
I think it's better to use a map function here
const productWithTitles = this.state.Product.filter((Product) => !!Product.title);
return (
<div>
{this.state.showExtraRows && (
<div>
{productWithTitles.slice(0, 3).map((product) => {
return (
<div>
//Display some fields here
</div>
);
})}
</div>
)}
</div>
);

Categories

Resources