event.preventDefault on child component which is calling parent function - React Js - javascript

I am not explaining my entire code structure. Here is my current situation. I have a method added to child component inside my parent component :
<TableRow obj={object} key={i} delteMethod={that.deleteRow} />
and my child component is defined like the below :
<a href="#" onClick={this.props.delteMethod.bind(this, this.props.obj.id)}>Delete</a>
This is my deleteRow() function in the parent component :
deleteRow(deleteid) {
var that = this;
deleteItem(deleteid).then(function(data){
that.loadData();
});
}
This works. I am able to get the obj.id back in my parent component and I am doing rest of the tasks. What I want to do is, I want to add an event.preventDefault() function to the 'Delete' button click (the child component button which I said already working fine). How to achieve this?

You could define a function in your child component that will receive event and call your parent's function from props. Here is an example code for your child component:
constructor(props) {
super(props);
this.onDeleteClick = this.onDeleteClick.bind(this);
}
onDeleteClick(event) {
event.preventDefault();
this.props.delteMethod(this.props.obj.id);
}
render() {
return (<a href="#" onClick={this.onDeleteClick}>Delete</a>);
}

you can have a click handler function in your component class like this
clickHandler = (e) => {
this.props.delteMethod(this.props.obj.id);
e.preventDefault();
}
and on the button you can have it like
<a href="#" onClick={this.clickHandler}>Delete</a>

Related

Pass the element itself as an onClick parameter instead of an instance of a class

I need to change the inner text of a button that is rendered by a class. Because of that, when I use the this keyword, React imagine that I want to pass the object of that class instead of the element itself.
Here I have my sample React code that doesn't work:
class Component extends React.Component {
helloWorld(element) {
element.innerText = 'Hello Wolrd!';
}
render() {
return (
<button onClick={this.helloWorld(this)}>Change it!</button>
)
}
}
And here I have a vanila JavaScript code that gets the expected result
<button onclick=helloWorld(this)>Change it!</button>
<script>
function helloWorld(element) {
element.innerText='Hello World!';
}
</script>
The keyword this in a React component refers to the component itself as you guessed.
You need to add a parameter event to the onClick method :
<button onClick={(e) => this.helloWorld(e.target)}>Change it!</button>

React Can I set button to do different things based on dropdown menu selection?

I have a dropdown menu on a form. Once the user chooses a selection, I'd like for the Submit button to do different requests based on the dropdown menu item selection. For example, if user chooses Apples, then Submit button fires a function1, while if user chooses Bananas, then Submit button fires a function2.
I have a parent component that looks like this:
class Container extends React.PureComponent {
_onSubmit = (date) => {
this.props.function1({
paramA: this.props.paramA,
paramB: this.props.paramB,
});
};
render() {
return (
<div>
<DownloadForm
dataSetName="Apples"
buttonText="Request Report"
onSubmit={this._onSubmit}
/>
</div>
);
}
}
Now, my DownloadForm component, which is nested here, will have a dropdown menu, and based on the dropdown menu's item, will have the onSubmit do something with a function2, which takes different parameters too.
I'm not sure how to do design this. I have 1 page as above, with the parent component that passes the onSubmit to it's nested component, and fires away to function1. I have another page as above, with the parent component also passing an onSubmit to the nested component, which fires away to function2.
How do I make it so that the dropdown menu item selection, inside the nested component, will then change it's button's onSubmit to fire away to function1 or function2 based on the dropdown menu item selected?
I hope my issue is clear.
Have a state that records the value of the dropdown selection inside the parent component. Inside _onSubmit() you check the state.
if (this.state.selection == "Apples") {
function1(param1, param2)
}
Here is a quick bit of code I put together that should get you started. It also takes into account some of #Mikes' comments
class Container extends React.Component {
constructor(props){
super(props);
this.state = {
selection: null
}
}
onSubmit = (date) => {
if (this.state.selection == "Apples") {
this.props.function1({
paramA: this.props.paramA,
paramB: this.props.paramB,
});
}
if (this.state.selection == "Bananas") {
this.props.function2({
paramA: this.props.paramA,
paramB: this.props.paramB,
});
}
};
handleSelectionChange = (selection) => {
this.setState({selection: selection})
}
render() {
return (
<div>
<Dropdown
onChange={this.handleSelectionChange}
/>
<DownloadForm
dataSetName="Apples"
buttonText="Request Report"
onSubmit={this._onSubmit}
/>
</div>
);
}
}

How do I get the id of a button that was clicked? ReactJS

I was wondering how I would go about getting the id (becuase it is unknown) of a button that is clicked. So when the button is clicked, I know what the id of that specific button is. There are lots of buttons on the page and I would like to know which button is pressed (they all have unique id's). Currently the buttons look like this:
<button key={uuidv4()} id={this.props.keyword} value={this.props.keyword} onClick={this.props.onClick} className="removeButton">Remove</button>
Well if the elements are nested event.target won't always work since it refers to the target that triggers the event in the first place. See this link for the usage of event.currentTarget, which always refer to the element that the handler is bound to.
Another way to grab hold of the element and its attributes is to use React refs. This is more general when trying to get the DOM element in React.
You can use event.target.id to get the ID of button clicked
class App extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
const id = event.target.id;
console.log(id);
}
render() {
return (
<button id="unique-id" onClick={this.handleClick}>Button</button>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
I know this has already been answered but i was working with react and faced similar issue, lost 2 hours trying to figure out why event.target.id was sometimes null or an empty string
this solved it for me:
class Button extends React.Component {
getButtonId = (e) => {
console.log(e.currentTarget.id);
}
render() {
return (
<button id="yourID" onClick={this.getButtonId}>Button</button>
);
}
}
You can use either event.target.[selector goes here] or event.currentTarget.[selector goes here] to solve your issue. See example code below.
class Button extends React.Component {
handleId = (e) => {
console.log(e.target.id);
console.log(e.currentTarget.id);
}
render() {
return (
<button id="yourID" onClick={this.handleId}>Button</button>
);
}
}
The very convenient way (not only for buttons but for list of elements) to do this is using custom attribute data-someName of DOM element and then reach it via event.currentTarget.dataset.someName
const openCard = (event) => {
console.log('event.currentTarget.dataset.id', event.currentTarget.dataset.id); // >> id
//do more actions with id
};
<Card onClick={openCard} data-id={item.id}>
<CardContent />
</Card>;
`
There is several way to do this
With manipulating onClick function
<button key={uuidv4()} id={this.props.keyword} value={this.props.keyword} onClick={(e)=>this.props.onClick(e,this.props.keyword)} className="removeButton">Remove</button>
onClick = (e,id) =>{
console.log(id);
}
Without manipulating onClick function
<button key={uuidv4()} id={this.props.keyword} value={this.props.keyword} onClick={this.props.onClick} className="removeButton">Remove</button>
onClick = (e) =>{
const id = e.target.getAttribute("id");
console.log(id);
}
You can do this:
function getId(id) {
console.log(id);
}
<button key={uuidv4()} id={this.props.keyword} value={this.props.keyword} onClick="getId(this.id)" className="removeButton">Remove</button>
if the function to handle the event is in the same component it is best to use the event.target.id, this will have its limitations when you try accessing a DOM element nested as a child component as event.target.id. Use event.currentTarget.id is nested,
This happens because event.currentTarget
can identify the element that caused the event deep down from the child as it burbles out, while event.target.id will set the target as the child component and will not be able to identify the child component that has that element since it target does not change and hence faulty.
You can watch this youtube video to understand better.
also read from their differences
Your onClick handler should receive the click event, which should include the id: event.target.id.
<button
key={uuidv4()}
id={this.props.keyword}
value={this.props.keyword}
onClick={(event) => /* you want to use event.target.id */}
className="removeButton">Remove</button>
This worked for me:
functionName = (event) => {
const id = event.target.id;
const value = event.target.value;
console.log("Value of the button: ", value)
console.log("Id of the button: ", id)}

How to remove element when clicking outside the element in javascript?

I have created a dropdown menu for my web app and when clicking on a icon i'm opening my dropdown menu. I want to remove the dropdown menu when i click anywhere other than the dropdown menu. My current approach removes the element when clicking outside the element. But i cannot open the dropdown menu when clicking on the icon after that. How can i fix it?
class DropDown extends Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
this.state = {
openmenu:false
}
};
myFunction(e) {
e.stopPropagation();
this.setState({
openmenu: !this.state.openmenu
})
render() {
window.onclick = function (event) {
if (!event.target.matches('myDropdown')) {
document.getElementById('myDropdown2').remove();
}
}
return (
<div className="dropdown small_font" id="myDropdown" >
<i className="fa fa-cog user_settings_icon" style={{marginTop: '6px'}} onClick={this.myFunction}
aria-hidden="true"></i>
{this.state.openmenu?
<div className="dropdown-content" id="myDropdown2">
<a className="dropdown_item"><i className="fa fa-trash-o margin_right10px" aria-hidden="true"></i>Delete</a>
<a className="dropdown_item"><i className="fa fa-flag-o margin_right10px" aria-hidden="true"></i>Report</a>
</div>:null
}
</div>
);
}
}
The error i'm getting when clicking on the icon for the second time
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
If you don't want to keep track of adding and removing click events on unmount and a solution that works across all browsers id recommend using a library. Ive used https://github.com/Pomax/react-onclickoutside and it works very well, heres a snippet.
import React, { Component } from "react";
import onClickOutside from "react-onclickoutside";
class MyComponent extends Component {
handleClickOutside = evt => {
// ..handling code goes here...
};
}
export default onClickOutside(MyComponent);
If you dont want to use a library use the onBlur
class MyComponent extends Component {
handleClickOutside = evt => {
// ..handling code goes here...
};
render(){
<div onBlur={this.handleClickOutside}>
<SomeChild />
</div>
}
}
Lastly your using React wrong, your using it as if it was jquery which it is not. you dont remove anything manually. You have state that you update when to close the dropdown and when to open it.
Using events such as window.onclick in render method is not a good practice since every time you update your state this event is going to be instantiated.
I also noticed you have created the state prop openmenu and myFunction but you not using them properly.
My suggestion is to attach DOM events in ReactJS's lifecycle events:
componentDidMount() {
window.addEventListener('onClick', this.myFunction)
}
componentWillUnmount() {
// Make sure to remove such event when your component is unmounted
window.removeEventListener('onClick', this.myFunction)
}

REACT: toggle class onClick, and call other function

I am new to react so please be patient - I'm sure this is a simple problem but I am having a lot of trouble figuring out a solution.
I have a set of buttons, when they are clicked I add an 'active' className to that button and remove it from any other buttons that might be active.
I also need to open a panel with content based on which button is clicked.
So far I have managed to toggle the className of the clicked button, but can't figure out how to only apply it to the button that is clicked (see code below)
<a onClick={this.buttonClick(1)} className={this.state.isButtonActive ? 'active' : null}>button text</a>
<a onClick={this.buttonClick(2)} className={this.state.isButtonActive ? 'active' : null}>button text</a>
and the function to toggle the active state and open appropriate panel based on the button clicked:
buttonClick(buttonNumber) {
this.setState(prevState => ({
isButtonActive: !prevState.isButtonActive
}));
openPanel(buttonNumber)
}
I have experimented with creating a child component for the button and toggling the className within the component, but then I can't trigger the openPanel() function as it is in the parent component.
I hope that makes sense - thank you in advance :)
the problem is that you are sharing the same state for both buttons, so when you change it for one, it changes for the other. You should wrap your buttons in different components so that they have different state.
If you need a callback in the parent component to be called, pass it to the button components so that they can trigger that as well.
The button could look like this:
class Button extends React.Component {
constructor () {
super()
this.state = { isButtonActive: false }
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({
isButtonActive: !this.state.isButtonActive
})
this.props.openPanel(this.props.buttonNumber)
}
render () {
return (
<button onClick={this.onClick()} className={this.state.isButtonActive ? 'active' : null}>button text</a>
)
}
}
how the parent component could look like:
class Parent extends React.Component {
onButtonClicked (number) {
console.log(`Button ${number} was clicked`)
}
render () {
return (
<div>
<Button buttonNumber={1} openPanel={this.onButtonClicked} />
<Button buttonNumber={2} openPanel={this.onButtonClicked} />
</div>
)
}
This happens because of the common state for both the button.
Instead of storing a boolean value for active, you can store the numeral like
<a onClick={this.buttonClick(1)} className={this.state.isButtonActive === 1 ? 'active' : null}>button text</a>
<a onClick={this.buttonClick(2)} className={this.state.isButtonActive === 2 ? 'active' : null}>button text</a>
and Click action to
buttonClick(buttonNumber) {
this.setState({
isButtonActive: buttonNumber
});
openPanel(buttonNumber)
}

Categories

Resources