Reputation: 473
I have a stateless function that maps and returns multiple list items. They already have a class assigned to them ("list-group-item"
), as you can see. I now want to assign a conditional CSS class to them as well, that will strike through the text of these list items (CSS class is named "strike-through"), based on when the input element is checked/unchecked.
This 'event' would be passed up through the prop onChange= {() => props.onDone(todo)}
so that that the stateful component is 'aware' of the change in there being a list item that is checked/unchecked.
How can I finish this logic so that a handler in my stateful component receiving the event, can toggle the condition (in the form of a boolean) based on the checked/unchecked box, then pass this condition back to my stateless component to change the class based on the condition (checked/unchecked)? (Checked boxes should have the CSS class, unchecked should not, based on the condition). For context please see below.
Stateless Function where I want a conditional class applied to the <li>
where there is a class already called "list-group-item"
and a prop onDone
in the <input>
that passes up change if a checkbox is checked/unchecked:
import React from 'react';
const Todo = props => (
<div className="container">
<div className="col-md-8">
<div className="panel panel-default">
<div className="panel-heading">Your Current Todos</div>
<ul className = "list-group">
{props.todo.map(todo => {
return <li className = "list-group-item" key ={todo.id}><input type="checkbox" onChange= {() => props.onDone(todo)}/>{todo.text}<a onClick={() => props.onEdit(todo)}
className="edit-todo glyphicon glyphicon-edit d-flex justify-content-between align-items-center" href="#"></a><a onClick={() => props.onDelete(todo)}
className="delete-todo glyphicon glyphicon-trash" href="#"></a></li>
})
}
</ul>
</div>
</div>
</div>
);
export default Todo;
State object:
class App extends Component {
constructor(props) {
super(props);
this.state = {
id: 0,
text: '',
editText: '',
editId: '',
priority: 1,
isEdit: false,
completed: false,
todos:[]
};
Handler that would receive event and toggle state (this.state.completed
is reserved for this):
handleComplete(todo){
//todo's properties can be accessed with todo.text for example if need to modify.
//Receives the event from my prop `onChange= {() => props.onDone(todo)}`
//Toggle this.state.completed so that based on this my stateless component can receive conditional styling
}
Upvotes: 1
Views: 151
Reputation: 3662
I'm not sure the shape of your todo data, I'm just going to assume your todos state is an array of todo objects. You can add a key like:
todo = {
id: 1,
text: "example",
completed: false
};
Your event handler would just need to toggle the completed state. Something like:
handleComplete = todo => {
this.setState({
todos: this.state.todos.map(el => {
if (el.id === todo.id) {
const newObj = Object.assign({}, el);
newObj.completed = !el.completed;
return newObj;
}
return el;
})
});
};
Then when mapping over your todo objects, you can change the className to a template string and apply a class conditionally like:
<li className=`{list-group ${completed && "strike-through"}}`>
Upvotes: 2
Reputation: 4163
If I understand your code correctly, you should just be able to conditionally determine the class name, based on the completed
property of your todo
variable. For example,
<li className={'list-group-item' + todo.completed ? ' strike-through' : ''} ... />
Upvotes: 1