Change button caption by condition React jsx - javascript

There is a button on the notes page with a deactivation function,
there is a note object (todo) it has an is_active property with a value of False or True , this property changes when clicked
please tell me how to make it so that when the button is pressed, the inscription changes along with the value: "Open" : "Closed", how and where to write the condition correctly. I found an option, but for some reason it does not work. Here is my note code:
const TodoItem = ({todo, deleteTODO}) => {
// <div>if todo.is_active === 'True' ? button:'Open' : button:'Closed'</div>
return (
<tr>
<td>{todo.id}</td>
<td>{todo.name_project}</td>
<td>{todo.text}</td>
<td>{todo.date_create}</td>
<td>{todo.date_update}</td>
<td>{todo.creator}</td>
{/*<td>{todo.is_active}</td>*/}
<td>
{todo.is_active === 'True' ?
<button onClick={() => deleteTODO(todo.id)} type='button'>Open </button>:
<button onClick={() => deleteTODO(todo.id)} type='button'>Closed </button>}
</td>
</tr>
)
}

I'm assuming that you want to change the text of button based on the boolean value of is_active then this would work.
<td>
<button onClick={() => deleteTODO(todo.id)}>
{ todo.is_active ? "Open" : "Close" }
</button>
</td>

Related

button onClick firing twice

#State() open: boolean = false;
...
...
private toggleSelect(source: string) {
console.log('fired ' + source);
this.open = !this.open;
console.log('toggleSelect: Open is now ' + this.open);
this.toggle.emit({ visible: this.open });
}
private handleSelect(value: string | undefined) {
this.value = value;
console.log('EMITTING ' + this.value);
this.changeValue.emit(this.value);
}
render() {
return (
<Host>
<button
class={`select ${this.open ? 'icon-open' : 'icon-closed'} ${
this.open ? 'select-open' : 'select-closed'
}`}
onClick={() => this.toggleSelect('button')}
>
<a> {this.getClosedDisplayValue(this.value)} </a>
<div class={`select-panel ${this.open ? 'open' : 'close'}`}>
{[{ value: 'undefined', name: '' }, ...this.data].map((item) => {
{
return (
<label class="checkmark" htmlFor={item.value}>
{this.getDisplayValue(item.value)}
<input
id={item.value}
title={this.getDisplayValue(item.value)}
name="select"
type="radio"
value={item.value}
onInput={(event) =>
this.handleSelect((event.target as HTMLInputElement).value)
}
/>
</label>
);
}
})}
</div>
</button>
<div
class={`overlay ${this.open ? 'open' : 'close'}`}
role="button"
onClick={() => this.toggleSelect('overlay')}
></div>
</Host>
);
}
}
I have the following code and what happens is when I open the drop down and select an item - I get this in the logs
*/opening the drop down
select.entry.js:39 fired button
select.entry.js:39 toggleSelect: Open is now true
*/selecting an option notice the double click event
select.entry.js:37 fired button
select.entry.js:39 toggleSelect: Open is now false
select.entry.js:37 fired button
select.entry.js:39 toggleSelect: Open is now true
select.entry.js:44 handling select was: true now is **FALSE**
is there a way to prevent this from being called twice or is because I have a input radio tag inside the button tag
I would ideally not want to have to hard code a this.open =false on the handle select method
This is a feature of React strict mode. React helps you detect side effects by running some functions twice. take a look: Why is console.log logging twice in react js?

How to get an alert message when changing the options in react?

I am having an ADD button which allows me to add some objects to the option that I selected in the dropdown. And I also have a function attached to that Add Button.
onAddClicked = () =>{
this.setState({
showOptions: true
});
}
<button type="button" onClick={this.onAddClick}
style={{ float: "right", marginLeft: "10px", marginRight: "10px" }}
id="AddSelectedTag"
className={((this.state.selectedOptions ?this.state.selectedOptions.length === 0 : true) ?
"re-btn-primary-inactive" : "re-btn-primary-blue")}disabled={(this.state.selectedOptions ?
this.state.selectedOptions.length === 0 : true) ? true : false}>Add
</button>
I can select and option and few objects under it. Now I need to display an error message when I want to change my option after selecting few objects under that. I am having state for my selected options as "this.state.selectedOptions".
I am trying
if(this.state.selectedOptions ? this.state.selectedOptions.value : null)
{
alert("selectedOptions value has changed");
}
But this is returning an alert message everytime I click on the Add button, not when I try to change the state.
onViewAllTagClick = (event) => {
this.setState({
showTagsSysController: true,
selectedOptions: event,
});
}
<li id="viewAllTags" className="re-exp-pak-edit-system-li">
<div className="re-lbl-normal-12">
<Select id="selectTags"
styles={ddlUtils.getSnapDdlStyle(200)}
placeholder="Select Tag, Network or Hardware "
options={[{label:"Tag",value:2,isChild:0},
{label:"Network",value:5,isChild:0},
label:"Hardware",value:3,isChild:0},
]}
value = { this.state.selectedOptions}
isSearchable={false}
isDisabled={this.state.isEdit === true}
noOptionsMessage={() => null}
onChange = {this.state.selectedSystems !== null ? this.onViewAllTagClick : null}>
</Select>
Add an event listener like componentDidUpdate and compare props
componentDidUpdate(prevProps) {
if(this.props.selectedOptions !== prevProps.selectedOptions)
alert("selectedOptions value has changed");
}

Add active class on a map items react

After map my array, I want to add an active css class if the user clicked on 1 element.
My map prototype :
publicationsPages.map((mod, i) => (
<div onClick={e => this.addActiveClass(i, e)} className=
{`${activeClasses[i] ? "active" : "inactive"} ${classes.modcontainer}
modcontainer`}>
<p className={`${classes.menuitems} menuitems`}>
{t(`Publications.${mod.name}`).toUpperCase()}
</p>
</div>
))
I have tried with a method called addActiveClass and a state :
this.state={activeClasses: [false, false, false, false]}
addActiveClass(index) {
const result = [...this.state.activeClasses.slice(0, index), !this.state.activeClasses[index], this.state.activeClasses.slice(index + 1)];
this.setState({activeClasses: result});
}
But that does not work.
Thank you in advance for your help
On the click of the element, you keep in your state the index of the selected item. In the item you can check if the index is the same as the index in the state and add the active class.
publicationsPages.map((mod, i) => (
<div
onClick={e => this.setState({activeIndex: i)}}
className= {`${i == this.state.activeIndex ? "active" : "inactive"}
>
...
</div>
))
Your default (or initial) value for activeIndex should be -1, then in the begging, no item will me active (if you want this).

React- input field turns to string after onChange

I have a small app with three components
parent => App
Son => Courses
Grandchild => Course
The app state lies in the App component, in the Course component I have an input field with an onChange event that spouse to change the state in the app component, the problem is that every time I type the input changes to a string and I can't keep typing and changing the state.
The values arrive to the parent.
This is my Course code
import React, { Component } from 'react'
class Course extends Component {
updatedGrade = (e) => {
this.props.updateCourseGrade(Number(e.target.value), Number(e.target.id));
};
render() {
const {id, courseType, courseName, courseGrade} = this.props.course;
return (
<tr key={id}>
<td>
{courseName}
</td>
<td>
{(courseType ? 'a' : 'm' )}
</td>
<td>
{(courseGrade !== ''
? courseGrade
: <input
type="number"
id={id}
onChange={this.updatedGrade}
value={courseGrade}
/>
)}
</td>
<td>
<button
onClick={this.props.removeCourse.bind(this, id)}
style={btnStyle}
>
remove
</button>
</td>
</tr>
)
}
}
this is my App relevant code:
class App extends Component {
state = {
courses: [
{
id: 1,
courseName: 'bioliogy,
courseType: false,
courseHours: 10,
courseGrade: ''
},{
id: 2,
courseName: 'Mahematics,
courseType: true,
courseHours: 20,
courseGrade: ''
},{
id: 3,
courseName: 'History,
courseType: false,
courseHours: 30,
courseGrade: 50
}
]
};
updateCourseGrade(courseGrade, id){
//const courseGradeNum = Number(courseGrade);
this.setState({
courses: this.state.courses.map(course => course.id === id ? {...course, courseGrade } : course)
})
console.log('courseGrade ', courseGrade);
Now, when I do this:
updateCourseGrade(courseGrade, id){
const courseGradeNum = Number(courseGrade);
this.setState({
courses: this.state.courses.map(course => course.id === id ? {...course, courseGradeNum } : course)
})
The state will get a new value while typing named courseGrade and I don't want this.
as well the courseGrade is already defined as a Number in the Course component
What can I do? maybe I shouldn't use value in the course component?
UPDATE
According to Freeman Lambda request, this is the state after I change the value in the input field,
the state of courseGrade of the desired course changes. but because the input field disappears I cannot keep typing.
Link to a video that shows what happens
https://www.screencast.com/t/Cyz1v6zMWsq
Here:
{(courseGrade !== ''
? courseGrade
: <input
type="number"
id={id}
onChange={this.updatedGrade}
value={courseGrade}
/>
)}
You explicitely change the input to a plain string a soon as courseGrade is !== ''
if you want to be able to keep typing you have to stick with an input during typing. If you want the input to disapear after typing you will have to add a button controlling a state that removes the input, for example:
class Course extends Component {
state = {
gradeValidated: false,
}
updatedGrade = (e) => {
this.props.updateCourseGrade(Number(e.target.value), Number(e.target.id));
};
toggleGradeInput = (e) => {
this.setState((state) => ({ gradeValidated: !state.gradeValidated }));
};
render() {
const {id, courseType, courseName, courseGrade} = this.props.course;
return (
<tr key={id}>
<td>
{courseName}
</td>
<td>
{(courseType ? 'a' : 'm' )}
</td>
<td>
{(this.state.gradeValidated
? courseGrade
: <input
type="number"
id={id}
onChange={this.updatedGrade}
value={courseGrade}
/>
)}
</td>
<td>
<button
onClick={this.toggleGradeInput}
style={btnStyle}
>
toggle input
</button>
<button
onClick={this.props.removeCourse.bind(this, id)}
style={btnStyle}
>
remove
</button>
</td>
</tr>
)
}
}
The problem is here
courseGrade !== ''
? courseGrade
: <input
type="number"
id={id}
onChange={this.updatedGrade}
value={courseGrade}
/>
the first condition is set to true if you set any state instead of '', so my idea is to use a save button for the grate and onChange keep on a local state.
You should use an updater function for this, I think what is happening is that state updates are getting batched.
So instead of
this.setState({
courses: this.state.courses.map(course => course.id === id ? {...course, courseGradeNum } : course)
})
try
this.setState( prevState => ({
courses: prevState.courses.map(course => course.id === id ? {...course, courseGradeNum } : course)
}))
If this wasn't the problem can you create a code sandbox because there just isn't enough code to understand what is going on. For example, updateCourseGrade is being bound anywhere. don't know if you haven't or if you are just not showing it.

Switching between buttons

How can i make dynamic switching between buttons? For example if one button is active, then the rest is not active. For example:
constructor(props) {
super(props)
this.state = {
active: false,
notactive: false
}
}
checkActive = () => {
this.setState({
active: true,
notactive: false
})
};
checkNotactive = () => {
this.setState({
active: false,
notactive: true
})
};
But i want make it dynamic.
I mean that when I have, for example, 10 buttons, I will not set each state apart. If I add another button, it will work. Just like the radio button.
Instead of a boolean you could use an index to mark the active button.
Eg:
this.state = {
activeButtonIndex: null
}
then when creating your buttons using a loop you can check
if (index === this.state.activeButtonIndex) { do something }
You would need to have a type property based on your buttons. If for example you need to make 3 buttons daily, weekly, monthly then you can have something like this.
return (
<div style={style.buttonContainer}>
<div className={this.props.active === "daily" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("daily")}>
Daily
</Button>
</div>
<div className={this.props.active === "weekly" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("weekly")}>
Weekly
</Button>
</div>
<div className={this.props.active === "monthly" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("monthly")}>
Monthly
</Button>
</div>
</div>
);
I have a property on parent's state active and based on that I will switch dynamically.

Categories

Resources