Outside Click handle event on element - javascript

can you tell me how can i handle a click on outside of element .For example i have that
<td><input type="number" className="hour" onKeyDown={this.editInlineHour(this)} /></td>
and i want only when i click outside of that element to execute some function and that is it in react !
I try it with that
window.addEventListener('mousedown', this.pageClick, false);
but even when i click on input field the function is executed.Thanks
This is my full code ..basically it is inline edit on field on table.. when i click on that field it show input field.. and i want when i click outside that field do go away
editInlineHour:function () {
},
showInlineEditHour:function (i) {
this.setState({
index:i,
showInlineHour:true
})
},
showInlineEditStart:function (i) {
this.setState({
index:i,
showInlineStart:true
})
},
showInlineEditEnd:function (i) {
this.setState({
index:i,
showInlineEnd:true
})
},
pageClick:function () {
this.setState({
showInlineStart:false,
showInlineEnd:false,
showInlineHour:false
});
},
render: function () {
var itemMap = this.state.items.map(function (item, i) {
var fieldDp1;
if(this.state.showInlineStart){
fieldDp1 = <input id="inlineDp1" className="flatpickr" data-date-format="m/d/Y"/>
}else{
fieldDp1 = <td onDoubleClick={this.showInlineEditStart.bind(this,i)} ><FormattedDate value={item.startDate}/></td>
}
var fieldDp2;
if(this.state.showInlineEnd){
fieldDp2 = <input id="inlineDp2" className="flatpickr" data-date-format="m/d/Y" />
}else{
fieldDp2 = <td onDoubleClick={this.showInlineEditEnd.bind(this,i)}><FormattedDate value={item.endDate}/></td>
}
var fieldHours;
if(this.state.showInlineHour){
fieldHours = <td><input type="number" className="hour" onKeyDown={this.editInlineHour(this)} /></td>
}else{
fieldHours = <td onDoubleClick={this.showInlineEditHour.bind(this,i)} >{item.workInHours}</td>
}
return (
<tr key={i}>
<td><input type="checkbox" checked={item.selected} onClick={this.handleChange.bind(this,i)} /></td>
{fieldDp1}
{fieldDp2}
{fieldHours}
<td><label type="button" onClick={this.handleShowModal.bind(this,i)}><img height="30px" src="moliv.jpg"/></label>
</td>
</tr>
);
}.bind(this));
return (
<div>
<button className="btn btn-primary center-block" onClick={this.addElem}>Add</button>
{this.state.list.theList.length > 0 ? <button className="btn btn-primary" onClick={this.putResult}>Put result</button> :null}
<table className="table scroll2">
<thead>
<tr className="danger">
<th><input type="checkbox" checked={this.state.allChecked} onClick={this.toggleAll}/></th>
<th>Start Date</th>
<th>End Date</th>
<th>Hours</th>
<th></th>
</tr>
</thead>
<tbody>
{itemMap}
</tbody>
</table>
{this.state.items.length > 0 ? <button type="button" className="btn btn-danger" onClick={this.deleteItems}>Remove</button> : null}
<Modal parentState={this.state} modalPropsId={this.props.theProps.id} handleHideModal={this.handleHideModal}/>
</div>
);

You can add ref to your element and check if click event comes outside of it.
function handleClickOutside(evt) {
if (this.refs.yourInput !== evt.target) {
callSomeFunction();
}
return true;
}
componentDidMount() {
this.clickHandler = handleClickOutside.bind(this);
document.addEventListener('click', this.clickHandler, true);
}
componentWillUnmount() {
document.removeEventListener('click', this.clickHandler, true);
}
In case if you want to check outside click for some component with children, you can use contains
if (!this.refs.yourComponent.contains(evt.target)) {
callSomeFunction();
}

Using that approach you will need to assign a onClick handler to your input element and stop propagation so that it doesn't propagate to the windows onClick event.
const handleInsideClick = (e) => {
e.stopPropagation();
}
React handles events in a smart way, an event is triggered from the deeper node in the DOM to the top, so when you click in the input you can either stop propagation to the onClick handler in the parent node or do whatever you want in the click event and let it propagate.

The event.preventDefault() method stops the default action of an element from happening if that what you're after.
<td><input type="number" id="inputField" className="hour" onKeyDown={this.editInlineHour(this)} /></td>
JavaScript:
$("#inputField").on("submit", function(event){
event.preventDefault(); // Stop event
event.stopPropagation(); // Stop event (react)
});
http://jsbin.com/nejetoxeve/edit?html,js,console,output

You can wrap Component with a component with a position: fixed like so:
import React, { Component } from 'react';
import ReactDom from 'react-dom';
const styles = (onClick) => ({
position: 'fixed',
pointerEvents: onClick ? 'auto' : 'none',
top: 0,
bottom: 0,
right: 0,
left: 0,
height: '100%',
});
export default class FixedLayer extends Component {
static defaultProps = {
zIndex: 2000,
onClick: null,
};
render () {
const divProps = { ...this.props };
delete divProps.zIndex;
return (
<div { ...divProps }
onClick={ (e) => this.props.onClick && (e.target === ReactDom.findDOMNode(this)) && this.props.onClick() }
style={{...this.props.style, ...styles(this.props.onClick), ...{zIndex: this.props.zIndex}}}>
{this.props.children}
</div>
)
}
}

Related

How to make open url on click on button in reactjs

In my code I am trying to do when I select row and click on button then this url open http://codeskulptor-assets.commondatastorage.googleapis.com/assets_clock_minute_arrow.png.
But right now in my code when I select row and click on button then url is not open.
How can we do that to open this url when I select row and click button the open url http://codeskulptor-assets.commondatastorage.googleapis.com/assets_clock_minute_arrow.png.
My code here https://codesandbox.io/embed/react-example-forked-o8tu5?codemirror=1
Anyone plz suggest any idea and help me out. I m stuck on that.
import React from 'react';
import axios from 'axios';
class ProvFileRptSearchResult extends React.Component {
constructor(props) {
super();
this.state = {
pymtDetails:[],
data: [],
rowDetails:[],
checkbox: false
};
// this.handleFile=this.handleFile.bind(this);
this.handleClick=this.handleClick.bind(this);
}
handleClick() {
const apiUrl = "http://localhost:9090/PrvFileRpt/getPrvFileData";
if (this.state.checkbox) {
fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
this.setState({ data: data });
console.log("This is your data", data);
window.open("https://example.com", "_blank");
})
} else {
alert("Data not fetched!");
}
// console.log('click');
}
// handleClick(e) {
// e.preventDefault();
// console.log("The link was clicked");
// }
// handleFile()
// {
// //fetch birt report from here
// console.log("inside file ",this.state.rowDetails);
// }
rowSelected(j) {
// e.preventDefault();
console.log(j)
const rownum=j;
console.log("rownum=",rownum)
console.log(this.props.customerDetails[rownum] )
this.setState({rowDetails:this.props.customerDetails[rownum]}, () => {
});
}
render()
{
return(
<div>
<div className="table-employee" style={{ marginTop:"20px",border:" 1.5px solid darkgray" }}>
<table className="table table-hover table-bordered table-sm">
<thead>
<tr >
<th scope="col">Select</th>
<th scope="col"> LOAD DATE</th>
<th scope="col"> FILE DATE</th>
<th scope="col"> SERVICE</th>
<th scope="col"> PROVISIONER CODE </th>
<th scope="col"> DESCRIPTION</th>
</tr>
</thead>
<tbody>
{
this.props.customerDetails.map((type,j)=>{
return(
<tr>
<td ><input type="radio" preventDefault name="select" key={j} onClick={(e) =>this.rowSelected(j)} value={this.state.checkbox}
onChange={(e) =>
this.setState({ checkbox: !this.state.checkbox })
}/></td>
<td> {type.provis_file_stamp}</td>
<td> {type.provis_file_hdrdt}</td>
<td> {type.service_code}</td>
<td>{type.provisioner_code}</td>
<td>{type.provisioner_desc}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
<div className="btn-submit" >
<button className="btn btn-primary" style={{marginRight:"30px"}} type="submit" onClick={this.handleClick}>FILE</button>
</div>
</div>
)
}
}
export default ProvFileRptSearchResult;
Call the openInNewTab with the URL. It will open the URL in a new browser tab. Remove '_blank', if you want to open it in the same tab.
const openInNewTab = (url) => {
const newWindow = window.open(url, '_blank', 'noopener,noreferrer')
if (newWindow) newWindow.opener = null
}
Well, if I understand correctly, you're trying to open a URL on button click?
If that's right, using window.open('https://example.com', '_blank') in your click handler will allow you to open any URL in a new tab.
First you need to find correct object using find method and then you can open url with window.open
Try following code:-
handleClick = () => {
const apiUrl = "https://mocki.io/v1/b512f8b8-64ab-46e4-9e0c-9db538a0ad9e";
if (this.state.checkbox) {
fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
this.setState({ data: data });
const urlData = data.find(element => element.id === 3); // filter data with id
window.open(urlData.url, '_blank'); // open url here
});
} else {
alert("check the radio!");
}
};

TypeError: Cannot read property 'name' of undefined react error

I can't seep to find the solution to this error in my code every time I try to type something in my input field. TypeError: Cannot read property 'name' of undefined
I'm new to react and don't know too much about.
Here is all the code in my file
import React from'react';
import Notelist from '../componenets/notelist';
import { Link } from 'react-router-dom';
export default class NewPage extends React.Component {
state = {
note:{
title: '',
body: '',
createdAt: undefined,
updatedAt: undefined
}
}
updateValue = (e) => {
const { note } = this.state;
this.setState({
note: { ...note, [e.title.name]: e.target.value }
});
}
handleSave = (e) => {
e.preventDefault();
const id = this.props.onSave(this.state.note);
this.props.history.replace(`/notes/${ id }`);
}
render() {
const { note } = this.state;
return (
<div className="note-form">
<h1>New Note</h1>
<form onSubmit={this.handleSave}>
<div className="note-form-field">
<label>Title: </label><br/>
<input className="input-txt" type="text" name="title" value={note.title} onChange={this.updateValue}/>
</div>
<div className="note-form-field note-form-field-text">
<br/>
<textarea name="body" value={note.body} onChange={this.updateValue} />
</div>
<div className="note-form-buttons">
<button className="btn">Save</button>
<Link to="/">Cancel</Link>
</div>
</form>
</div>
);
}
}
This is the full error I get:
TypeError: Cannot read property 'name' of undefined
NewPage.updateValue
C:/Users/user/react-notes/src/pages/new.js:20
17 | const { note } = this.state;
18 |
19 | this.setState({
> 20 | note: { ...note, [e.title.name]: e.target.value }
| ^ 21 | });
22 | }
23 |
View compiled
The event object (e) does not have a key called title which is why you get "Cannot read property name of undefined".
You need event.target, which refers to the element that is causing this event to occur.
Try the following to dynamically update a state-value. It will find a key that matches the name of the element, and give it the value coming to that element (like user input):
updateValue = (e) => {
const { note } = this.state;
this.setState({
note: { ...note, [e.target.name]: e.target.value }
});
}
I believe you are trying to assign title as key and value of the input field as value. why don't you just try this?
updateValue = (e) => {
const { note } = this.state;
this.setState({
note: { ...note, "title": e.target.value }
});
}
the param e in the updateValue method is event object, it will not have a property called title.name. If you want to store the value of the title textbox to the property title of note object
So your code can be like this
this.setState({
note: { ...note, title: e.target.value }
});
import React, { Component } from 'react'
export class Todolist2 extends Component {
state={name:'',items:'',price:'',arr:[],errors:{name:'',items:'',price:''}}
todoSubmit=(event)=>
{
event.preventDefault()
let list=this.state.arr;
let tododata={name:this.state.name, items:this.state.items, price:this.state.price};
list.push(tododata);
this.setState({arr:list});
console.log(this.state.arr);
}
handle=(event)=>
{
const {name,value}=event.target;
let errors=this.state.error;
switch(errors)
{
case 'name':errors.name=value.length<2?"Name must be 2 character long":'';
case 'items':errors.items=value.length<2?"items must be 2 character long":'';
case 'price':errors.price=value.length<2?"price must be 2 character long":'';
}
this.setState({errors,[name]:value})
this.setState({[name]:value})
console.log(this.state);
}
deldata=(ind)=>
{
if (window.confirm('Do u want to delete'))
{
let list=this.state.arr;
list.splice(ind,1);
this.setState({arr:list});
}
// alert('do u want to delete');
}
render() {
const {errors}=this.state;
return (
<div>
<h1>ToDo List 2</h1>
<form className='container' onSubmit={this.todoSubmit}>
<div className="form-group col-md-4">
<label>Name:</label>
<input type="text" name="name" className='form-control' onChange={this.handle}/>
{errors.name.length>0 && <span className='alert alert-danger'>{errors.name}</span> }
</div>
<div className="form-group col-md-4" onChange={this.handle}>
<label>Items:</label>
<input type="text" name="items" class='form-control'/>
{errors.items.length>0 && <span className='alert alert-danger'>{errors.items}</span> }
</div>
<div className="form-group col-md-4" onChange={this.handle}>
<label>Price:</label>
<input type="text" name="price" class='form-control'/>
{errors.price.length>0 && <span className='alert alert-danger'>{errors.price}</span> }
</div>
<input type='Submit' value='Submit' class='btn btn-outline-success' />
<table class='table'>
<tr>
<th>S.no</th>
<th>Name</th>
<th>Items</th>
<th>Price</th>
<th>Action</th>
</tr>
{this.state.arr.map((data,ind)=>
<tr>
<td>{ind+1}</td>
<td>{data.name}</td>
<td>{data.items}</td>
<td>{data.price}</td>
<td><button class="btn btn-info btn-lg " onClick={()=>this.deldata(ind)}>delete </button></td>
</tr>
)}
</table>
</form>
</div>
)
}
}
export default Todolist2

show/hide table data on the basis of selected checkbox in vue js and hide/show button

I want to show/hide my table data. when I checked the checkboxes and on after a button click I want to hide them and vice versa.
I am able to put checkbox value to another inactiveList as an array but not able to bind to button.
this is my component file.....
<button class="btn btn-lg btn-primary" v-on:click="seen(inactiveList)">hide/show</button>
<table class="row-border hover">
<tr>
<th>Id</th>
<th>Title</th>
<th>UserId</th>
<th>Change Detail</th>
<th>Add Detail</th>
</tr>
<tr v-for = "(item,index) in paginate " :key= "index">
<td>{{item.id}}</td>
<td>{{item.title}}</td>
<td>{{item.userId}}</td>
<td><button class="btn btn-primary" >Edit</button></td>
<td><button class="btn btn-primary" >Add</button></td>
<td> <input type="checkbox" name="vehicle1"
v-on:change="list" v-bind:value="item" v-model="inactiveList"><br></td>
</tr>
</table>
<ul>
<li v-for="pageNumber in totalPages" v-if="Math.abs(pageNumber - currentPage) < 3
|| pageNumber == totalPages || pageNumber == 1">
<a v-bind:key="pageNumber" href="#" #click="setPage(pageNumber)"
:class="{current: currentPage === pageNumber,
last: (pageNumber == totalPages && Math.abs(pageNumber - currentPage) > 3),
first:(pageNumber == 1 && Math.abs(pageNumber - currentPage) > 3)}">{{ pageNumber }}</a>
</li>
</ul>
</div>
export default {
name: 'component2',
data(){
return{
currentPage: 1,
itemsPerPage: 10,
resultCount: 0,
inactiveList:[],
selected:false,
}
},
computed: {
...mapState([
'posts',
'loading'
]),
totalPages: function() {
return Math.ceil(this.resultCount / this.itemsPerPage)
},
paginate: function() {
debugger
if (!this.posts || this.posts.length != this.posts.length) {
return
}
this.resultCount = this.posts.length
if (this.currentPage >= this.totalPages) {
this.currentPage = this.totalPages
}
var index = this.currentPage * this.itemsPerPage - this.itemsPerPage
return this.posts.slice(index, index + this.itemsPerPage)
},
},
methods: {
setPage: function(pageNumber) {
this.currentPage = pageNumber
},
list: function(){
if(this.selected==false)
{
this.paginate.push= this.inactiveList;
return this.inactiveList
}
},
seen: function(inactiveList){
var index = this.inactiveList.length;
for(var i=0;i<index;i++)
{
this.inactiveList[i].id;
console.log(inactiveList[i].id)
}
},
},
mounted() {
this.$store.dispatch('loadPost');
},
}
</script>
this is my store.js file.....
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";
Vue.use(Vuex,axios);
export const store = new Vuex.Store({
state: {
posts:[],
loading: true
},
mutations:{
set_post(state,posts){
state.posts=posts;
},
changeLoadingState(state, loading) {
state.loading = loading
}
},
actions:{
loadPost({commit})
{
axios
.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
let post = response.data
console.log(post)
commit('set_post',post);
commit('changeLoadingState', false)
})
.catch(error => {
console.log(error)
this.errored = true
})
},
}
})
If I unterstood you correctly, you want to toggle visibility of each row and a possibility to unhide all hidden items.
To do that you should give each item a boolean flag if its currently visible or not.
You can store that in your data directly on each item as a property or make create an array based on index, if it's sorted data, or a map, if the sort of items happens to change anyway.
data() {
return {
useVisibility: false,
items: {} // id -> item
};
},
Don't forget to populate the map regarding this example code.
Now as you have provided the state you have to bind the inputs to each items boolean flag
<input type="checkbox" name="item.name" #change="setVisibility(item.id, $event)" :value="item.visible" />
Provide a method to change the visibility flag
setVisibility(id, event) {
Vue.set(this.items, id, { ...this.items[id], visible: event.target.checked})
}
Read up on the reactivity system if you don't know why I used Vue.set here. But maybe there is a better way to update the flag anyways.
To unhide all hidden items you just need to iterate over all items and set the visible flag to true with an v-on:click handler.
Write a computed property to get a list of visible items
computed: {
visibleItems() {
if (this.useVisibility) {
// filter unchecked boxes
return Object.values(this.items).filter(item => item.visible)
// to filter checked boxes use the invert
// return Object.values(this.items).filter(item => !item.visible)
} else {
return Object.values(this.items)
}
}
}
And render the list with a v-for. Notice. Use the id of the item so the VDOM can do its work properly.
<tr v-for="(item, index) in visibleItems" :key="item.id">
...
<input type="checkbox" name="item.name" #change="setVisibility(item.id, $event)" :checked="item.visible" />
</tr>
A button that hides/shows all checked items.
<button #click="useVisibility = !useVisibility"/>
See this demo

Select all checkbox of table on click of the another table checkbox using react

I have checkboxes for each td in a table. Now, I have another table which has one checkbox. On checking this, I want to select all other checkboxes of first table.
Here is the code,
<tr key={key}>
<td align="center"> <input type="checkbox" name="myTextEditBox" value="checked" /></td>
<td>{item.technology}</td>
</tr>
for second table I did,
handleCheckBox = () => {
console.log("callling the handle change");
this.setState({
isCheckd: !this.state.isCheckd
})
}
constructure(props) {
this.state = { isCheckd: false }
<td className="text-right mr-1"><input type="checkbox" checked={this.state.isCheckd} onChange={this.handleCheckBox} /></td>
}
Now, In this click handler works. But, now how do I select all other checkboxes of another table, without using jquery.
Can any one help me with this ?
Tried solution -
state = { dynamicProp: {}, isCheckd: false,}
handleCheckBox = () => {
this.setState({
isCheckd: !this.state.isCheckd
}, () => {
this.props.jobs.forEach((item) =>
this.setState(prevState => ({
dynamicProp: {
...prevState.dynamicProp,
[item.jdName]: prevState.isCheckd
}
})
))
});
}
handleTableCheckboxChange = (e) => {
const target = e.target.name;
const checked = e.target.checked;
this.setState(prevState => ({
dynamicProp: {
...prevState.dynamicProp,
[target]: checked
}
}), () => {
const result = this.allTrue(this.state.dynamicProp);
this.setState({
isCheckd: result ? false : true
})
})
}
allTrue(obj) {
for (var o in obj)
if (!obj[o]) return true;
return false;
}
and then passing all the props to the child element. Now, the problem I am facing now is in the handleTableCheckboxChange method where I am not getting the way you used filter to get the unchecked element. and then the select all check will get changed.
I did not understand your code well so I understand it from what you have written. And then I have created a working example for you. Hope it can help you!
UPDATED CODE
const Table=(props)=>(
<table>
{
props.items.map((item, i) => (
<tr key={i}>
<td>
<input type="checkbox" checked={props.parentState[item.name]} name={item.name} onChange={props.handleChange} />
</td>
<td>{item.value}</td>
</tr>
))
}
</table>
);
class App extends React.Component {
items = [
{
value: 'EN',
name: 'field1'
},
{
value: 'IT',
name: 'field2',
}
];
state = {
checkAll: false,
};
render() {
return (
<div>
Check All
<input type="checkbox" onChange={this.handleCheckAll} checked={this.state.checkAll}/>
<Table
handleChange={this.handleChange}
items={this.items}
parentState={this.state}
/>
</div>
);
}
handleCheckAll = () => {
this.setState({
checkAll: !this.state.checkAll
}, () => {
this.items.forEach((item) => this.setState({ [item.name]: this.state.checkAll}))
});
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.checked
}, () => {
const uncheckedItems = this.items.filter((item) => !this.state[item.name])
this.setState({
checkAll: uncheckedItems.length === 0?true:false
});
});
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Here's a sample code. Obviously i haven't covered all the fail cases. Still you will get an idea about how that can be done.
import React from 'react';
export default class CheckboxIndex extends React.Component{
constructor(props){
super(props);
this.state = {
isChecked : false,
allTDS : [
{name:"name 1",value:false},
{name:"name 2",value:false},
{name:"name 3",value:false},
{name:"name 4",value:false},
{name:"name 5",value:false},
{name:"name 6",value:false},
{name:"name 7",value:false}
]
}
}
handleCheckBox = () => {
this.setState({isChecked: !this.state.isChecked});
let tempTDS = this.state.allTDS;
for (let i =0; i < tempTDS.length; i++){
tempTDS[i].value = !this.state.isChecked;
}
this.setState({allTDS : tempTDS});
};
render(){
let listOfTR;
if(this.state.allTDS.length){
listOfTR = this.state.allTDS.map((item,index)=>{
return(
<tr key={item.name}>
<td>
<label htmlFor={item.name}>
<input id={item.name} checked={item.value} type="checkbox"
onChange={()=>{
let tempObj = this.state.allTDS;
tempObj[index].value = !tempObj[index].value;
this.setState({allTDS:tempObj});
}}/>{item.name}
</label>
</td>
</tr>
)
})
}
return(
<div>
<label htmlFor="allTDS">
<input type="checkbox" id="allTDS" name="all" checked={this.state.isChecked}
onChange={this.handleCheckBox}/> All
</label>
<table>
<tbody>
{listOfTR}
</tbody>
</table>
</div>
)
}
}
class CheckboxTest extends React.Component {
constructor() {
super();
this.state = {
selectAll: false,
data1: false,
data2: false
};
this.selectAll = this.selectAll.bind(this);
this.selectField = this.selectField.bind(this);
}
selectAll() {
this.setState({
data1: !this.state.selectAll,
data2: !this.state.selectAll,
selectAll: !this.state.selectAll
});
}
selectField(event) {
if (event.target.value === "data1")
this.setState({ data1: !this.state.data1 });
else this.setState({ data2: !this.state.data2 });
}
render() {
return (
<div className="App">
<table>
<tbody>
<tr>
<td align="center">
<input
checked={this.state.data1}
onChange={this.selectField}
type="checkbox"
name="myTextEditBox1"
value="data1"
/>
</td>
<td>data 1</td>
</tr>
<tr>
<td align="center">
<input
checked={this.state.data2}
onChange={this.selectField}
type="checkbox"
name="myTextEditBox2"
value="data2"
/>
</td>
<td>data 2</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td align="center">
<input
onChange={this.selectAll}
type="checkbox"
name="myTextEditBox1"
value="all"
/>
</td>
<td>Click all</td>
</tr>
</tbody>
</table>
</div>
);
}
}
You can use the state for implementing this. Maintain state for each checkbox field and when the checkbox is changed trigger a method to set the state according to your conditions
this.setState({
isCheckd: !this.state.isCheckd
})
In this case, the isCheckd value in state corresponds to one checkbox. To select all other checkboxes of another table you have to update the values set in setState to all the values that correspond to all the boxes you want checked.
So if you have another 3 checkboxes who's values correspond to isCheckd1, isCheckd2, and isCheckd3 in state then your handler would be:
this.setState({
isCheckd1: true,
isCheckd2: true,
isCheckd3: true
})
Try this approach. you can select both the individual and check all checkbox.
class App extends React.Component {
items = ['EN', 'IT', 'FR', 'GR', 'RU'];
state = {
checkAll: false,
items : [
{'label': 'EN', 'checked': false},
{'label': 'IN', 'checked': false},
{'label': 'FR', 'checked': false},
]
};
render() {
return (
<div>
Check All
<input type="checkbox" onChange={this.handleCheckAll} />
<table>
{
this.state.items.map((item, i) => (
<tr key={i}>
<td>
<input type="checkbox" checked={item.checked} />
</td>
<td>{item.label}</td>
</tr>
))
}
</table>
</div>
);
}
handleCheckAll = () => {
let checkAll = !this.state.checkAll;
let items = this.state.items;
items.map((item, i) => {
item.checked = checkAll;
});
this.setState({
checkAll,
items
});
}
}

React: e.target.getAttribute ("id") works 20% of the time?

I'm new to React and been trying to fix this for hours. I'm trying to get the id of the button which is clicked But this only gets the id around 20% of the time and the rest it returns nulltext. I have no idea what else to do. I have tried different binding methods but haven't been able to make it work.
I simplified the code here and put it below.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class Popupright extends React.Component {
popupnewshow = (e) => {
let ids = e.target.getAttribute("id") + "text";
console.log(ids)
let elements = document.getElementsByClassName('poprighttext showtext');
while(elements.length > 0){
elements[0].classList.remove('showtext');
};
document.getElementById(ids).classList.toggle("showtext");
};
render() {
return (
<div>
<table className="table-bordered">
<tbody>
<tr className="table-samewidth">
<td className="td-general"><button className="popup" id="xxx" onClick={this.popupnewshow}><div className="popuptitle">xxx</div></button></td>
</tr>
<tr className="table-samewidth">
<td className="td-general"><button className="popup" id="yyy" onClick={this.popupnewshow}><div className="popuptitle">yyy</div></button></td>
</tr>
<tr className="table-samewidth">
<td className="td-general"><button className="popup" id="zzz" onClick={this.popupnewshow}><div className="popuptitle">zzz</div></button></td>
</tr>
</tbody>
</table>
<div id="xxxtext" className="poprighttext">
<p>xxx.</p>
</div>
<div id="yyytext" className="poprighttext">
<p>yyy</p>
</div>
<div id="zzztext" className="poprighttext">
<p>zzz</p>
</div>
</div>
);
}
}
export default Popupright;
Console Image: The buttons should give the id xxxtext, yyytext or zzztext depending on the button clicked but this only works 20% of the time. The rest it returns nulltext and after some clicks it returns again the proper id:
Using e.currentTarget.id should solve your issue.
e.target holds the element that you clicked on, but e.currentTarget will hold the element where you have bind the handler.
When you use e.currentTarget:
<button className="popup" id="xxx" onClick={this.popupnewshow}>
<div className="popuptitle">xxx</div><!-- clicking on here:
e.currentTarget.id is xxx -->
</button>
When you use e.target:
<button className="popup" id="xxx" onClick={this.popupnewshow}>
<div className="popuptitle">xxx</div><!-- clicking on here:
there's no id here (the clicked element id) -->
</button>
In general better to avoid direct DOM manipulation like remove. Also you can get the id directly rather than from the event:
const toggleItem = (arrayOfObjects, objectId) => {
//some implementation of toggle object's vislble prop based on id property in array
}
class Popupright extends React.Component {
state = {
popups: [
{id: 'xxx', text: 'xxxtext', visible: false},
{id: 'yyy', text: 'yyytext', visible: false},
...
]
}
togglePopup = id => {
this.setState(prevState => ({
popups: [...toggleItem(prevState.popups, id)]
})
}
render() {
return (
<table>
...
<td>
<button onClick={() => this.togglePopup('xxx')} />
</td>
...
</table>
<div className="popupsWrap">
{this.state.popups.map(popup => {
if (popup.visible) {
return (
<div className="poprighttext">{popup.text}</div>
)
}
}}
</div>
...

Categories