I am displaying data in the checkboxlist. I have implemented Select All and ClearAll buttons that selects all or unselect all checkboxes.
Please find my react code in the sandbox: https://codesandbox.io/s/immutable-pond-07qnue
Please fix my code why SelectAll and ClearAll functionality is not working.
import React from "react";
const data = [
{ templateID: "11", templateName: "All" },
{ templateID: "21", templateName: "SC" }
];
export class Delete_Item extends React.Component {
constructor(props) {
super(props);
this.state = {
Template_ID: "",
TemplateName: "",
Templatelist: [],
checkedItems: []
};
this.handleChange = this.handleChange.bind(this);
this.handleSelectAll = this.handleSelectAll.bind(this);
this.handleClearAll = this.handleClearAll.bind(this);
}
componentDidMount() {
this.getTemplateList();
}
getTemplateList() {
this.setState({
Templatelist: data,
TemplateName: data[0].templateName,
loading: false
});
console.log(this.state.Templatelist);
}
handleChange(event) {
const id = parseInt(event.target.id, 10);
const index = this.state.checkedItems.indexOf(id);
const updatedArray = [...this.state.checkedItems];
if (index !== -1) {
updatedArray.splice(index, 1);
} else {
updatedArray.push(id);
}
this.setState((prevState) => ({
checkedItems: updatedArray
}));
console.log(this.state.checkedItems);
}
handleSelectAll() {
return this.setState({
checkedItems: this.state.Templatelist.map((id) => id)
});
}
handleClearAll() {
return this.setState({ checkedItems: [] });
}
render() {
return (
<div>
<ul style={{ listStyle: "none" }}>
{this.state.Templatelist.map((item, index) => {
return (
<li key={item.templateID}>
<input
type="checkbox"
id={item.templateID}
value={item.templateName}
onChange={this.handleChange}
/>
{item.templateName}
</li>
);
})}
</ul>
<input
type="button"
name="SelectAll"
value="Select All"
onClick={this.handleSelectAll}
/>
<input
type="button"
name="UnSelectAll"
value="Clear All"
onClick={this.handleClearAll}
/>
</div>
);
}
}
export default Delete_Item;
You need to add the checked property to your checkbox based on what you have selected this.state.checkedItems. Also in handleChange method you convert it to an integer and stored while in handleSelectAll method you use the full object. So need to make sure to store at the same type.
import React from "react";
const data = [
{ templateID: "11", templateName: "All" },
{ templateID: "21", templateName: "SC" }
];
export class Delete_Item extends React.Component {
constructor(props) {
super(props);
this.state = {
Template_ID: "",
TemplateName: "",
Templatelist: [],
checkedItems: []
};
this.handleChange = this.handleChange.bind(this);
this.handleSelectAll = this.handleSelectAll.bind(this);
this.handleClearAll = this.handleClearAll.bind(this);
}
componentDidMount() {
this.getTemplateList();
}
getTemplateList() {
this.setState({
Templatelist: data,
TemplateName: data[0].templateName,
loading: false
});
}
handleChange(event) {
const id = event.target.id;
const index = this.state.checkedItems.indexOf(id);
const updatedArray = [...this.state.checkedItems];
if (index !== -1) {
updatedArray.splice(index, 1);
} else {
updatedArray.push(id);
}
this.setState({
checkedItems: updatedArray
});
}
handleSelectAll() {
this.setState({
checkedItems: this.state.Templatelist.map((id) => id.templateID)
});
}
handleClearAll() {
this.setState({ checkedItems: [] });
}
render() {
return (
<div>
<ul style={{ listStyle: "none" }}>
{this.state.Templatelist.map((item, index) => {
return (
<li key={item.templateID}>
<input
type="checkbox"
id={item.templateID}
value={item.templateName}
checked={this.state.checkedItems.some(
(i) => i === item.templateID
)}
onChange={this.handleChange}
/>
{item.templateName}
</li>
);
})}
</ul>
<input
type="button"
name="SelectAll"
value="Select All"
onClick={this.handleSelectAll}
/>
<input
type="button"
name="UnSelectAll"
value="Clear All"
onClick={this.handleClearAll}
/>
</div>
);
}
}
export default Delete_Item;
Sample working at https://codesandbox.io/s/prod-darkness-l2vx52
Related
I am displaying data in the checkboxlist. How to implement Select All and UnselectAll buttons that selects all or unselect all checkboxes. Please find my react code and data coming from api.
[ {"templateID":"11","templateName":"All” },
{"templateID":"21","templateName":"SC" }]
import React from "react";
export class Delete_Item extends React.Component {
constructor(props) ;
super(props);
this.state = {
Template_ID: "",
TemplateName: "",
Templatelist: [],
checkedItems: [],
};
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
this.getTemplateList();
}
getTemplateList() {
fetch(REQUEST_URL, { credentials: 'include' })
.then(response => response.json())
.then((data) => {
this.setState({
Templatelist: data,
TemplateName: data[0].templateName,
loading: false
})
console.log(this.state.Templatelist);
})
}
handleChange(event) {
const id = parseInt(event.target.id, 10);
const index = this.state.checkedItems.indexOf(id);
const updatedArray = [...this.state.checkedItems];
if (index !== -1) {
updatedArray.splice(index, 1);
} else {
updatedArray.push(id);
}
this.setState((prevState) => ({
checkedItems: updatedArray
}));
console.log(this.state.checkedItems);
}
render() {
return (
<div>
<ul style={{ listStyle: 'none' }} >
{
(this.state.Templatelist.map((item, index) => {
return (
<li key={item.templateID}>
<input type="checkbox" id={item.templateID} value={item.templateName}
onChange={this.handleChange} />
{item.templateName}</li>)}))}</ul>
<input type="button" name="SelectAll" value="Select All" />
<input type="button" name="UnSelectAll" value="Clear All" />
</div>
);
}
}
export default Delete_Item;
thanks
selectAll() {
return this.setState({ checkedItems: this.state.Templatelist.map(id => id) });
}
unselectAll() {
return this.setState({ checkedItems: [] });
}
I'm trying to make an event on todoList to check out the box, the event is called checkBox in my code, but I'm stuck and cannot figure it out. I'm very new to Javascript and React, could you please help me. I think there is something wrong here:
{this.state.itemList.map((item, index) => (
{item.todo}{item.completed}
checkBox={this.checkBox}
this.checkBox(item.completed)}
/>
))}
I cannot quite figure it out yet, here is my full code
import React, { Component } from 'react'
export default class TodoList extends Component {
constructor(props) {
super(props)
this.state = {
todo:"",
completed: "",
itemList: [
{ todo: "Take out the Trash", completed: true },
{ todo: "Water the plants", completed: false },
{ todo: "Grocery shopping", completed: true }
]
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.checkBox = this.checkBox(this)
}
handleChange(e) {
this.setState({todo: e.target.value});
}
handleSubmit(n) {
this.setState({
itemList: [...this.state.itemList, {todo: this.state.todo, completed: false}],
});
}
checkBox(event) {
this.setState(prev =>{
const newList = prev.itemList.map(todo => {
if (todo.event === todo) {
todo.completed = !todo.completed
}
return todo
})
return {itemList: newList
}
})
}
render() {
return (
<div className="container">
<div className="main">
<div>
<input className="header w-50 p-2" type="text" placeholder="enter task" value={this.state.todo} onChange={this.handleChange}/><br></br>
<button className="button btn-btn-primary ml-1 mt-3" onClick={this.handleSubmit}>Submit</button>
</div>
<div>
{this.state.itemList.map((item, index) => (<p className="mt-4 list" key={index}>{item.todo}{item.completed} checkBox={this.checkBox} <input type="checkbox" onChange={()=>this.checkBox(item.completed)}/></p>))}
</div>
</div>
</div>
)
}
}
You did not bind the checkBox function properly in the constructor, I fixed it below and commented where the issue was:
constructor(props) {
super(props)
this.state = {
todo:"",
completed: "",
itemList: [
{ todo: "Take out the Trash", completed: true },
{ todo: "Water the plants", completed: false },
{ todo: "Grocery shopping", completed: true }
]
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.checkBox = this.checkBox.bind(this)// correctly bound function, instead of 'this.checkBox = this.checkBox(this)'
}
Implemented writing data from the form to the array. Everything works. but now I want to implement data output when I click on " SEND ARR "
When I hang up a click on a button, respectively, the data is not displayed since in the function we access event.target.value
Please tell me how to rewrite the line so that I can display data when I click on the button? thank
home.js
import React from "react";
import "./../App.css"
export default class Home extends React.Component {
constructor() {
super()
this.state = {
count: 1,
objexm: '',
inputValue: '',
arr: []
}
this.handleClick = this.handleClick.bind(this);
this.updateInputValue = this.updateInputValue.bind(this);
}
handleClick() {
this.setState({
count: this.state.count + 1
});
};
createMarkup() {
return {
__html: this.state.inputValue
};
};
updateInputValue(event) {
let newArr = this.state.arr;
let newlist = event.target.value;
if (event.target.value) {
newArr.push(newlist)
}
this.setState({
inputValue: newArr
});
event.target.value = '';
};
render() {
return (
<div className="home-header">
<h2>{this.state.count}</h2>
<button onClick={this.handleClick}>Add</button>
<input type='text' name="names" onClick={this.updateInputValue} />
{this.state.arr.map((arrs, index) => {
return (
<li
key={index}
>{arrs}</li>
)
})}
<button>SEND ARR</button>
<ul className="qwe">
<li dangerouslySetInnerHTML={this.createMarkup()}></li>
</ul>
</div>
);
}
}
Store the data from the input into invputValue each time the input is updated and on the click of the button update the arr content with the old values (...arr) plus the current input value (this.state.inputValue) .
To make sure the old values are not deleted the arr is defined at the top of the class let arr = []. If you don't want it there you can instantiate it in the constructer which will run only once. i.e. this.arr = []
let arr = []
class Home extends React.Component {
constructor() {
super()
this.state = {
count: 1,
objexm: '',
inputValue: '',
arr: []
}
this.handleClick = this.handleClick.bind(this);
this.updateInputValue = this.updateInputValue.bind(this);
}
handleClick() {
this.setState({
count: this.state.count + 1
});
};
createMarkup() {
return {
__html: this.state.inputValue
};
};
updateInputValue = e => {
this.setState({ inputValue: e.target.value })
}
displayData = () => {
arr = [...arr ,this.state.inputValue]
this.setState({ arr, inputValue: "" })
}
clearData = () => {
this.setState({ arr: [] })
}
render() {
console.log("this.state.arr:", this.state.arr)
return (
<div className="home-header">
<h2>{this.state.count}</h2>
<button onClick={this.handleClick}>Add</button>
<input type='text' name="names" onChange={this.updateInputValue} value={this.state.inputValue} />
{this.state.arr.map((arrs, index) => {
return (
<li
key={index}
>{arrs}</li>
)
})}
<button onClick={this.displayData}>SEND ARR</button>
<button onClick={this.clearData}>CLEAR ARR</button>
<ul className="qwe">
<li dangerouslySetInnerHTML={this.createMarkup()}></li>
</ul>
</div>
);
}
}
Instead of using onClick on input, use onChange and update value in state i.e. make the input a controlled component . Post that onClick of button take the value from state and push to the array and clear the input value
export default class Home extends React.Component {
constructor() {
super()
this.state = {
count: 1,
objexm: '',
inputValue: '',
arr: []
}
this.handleClick = this.handleClick.bind(this);
this.updateInputValue = this.updateInputValue.bind(this);
}
handleClick() {
this.setState(prevState => ({
count: prevState.count + 1,
inputValue: [...prevState.inputValue, prevState.name],
name: ""
}));
};
createMarkup() {
return {
__html: this.state.inputValue
};
};
updateInputValue(event) {
let newVal = event.target.value;
this.setState({
name: newVal
});
};
render() {
return (
<div className="home-header">
<h2>{this.state.count}</h2>
<button onClick={this.handleClick}>Add</button>
<input type='text' name="names" value={this.state.name} onChange={this.updateInputValue} />
{this.state.arr.map((arrs, index) => {
return (
<li
key={index}
>{arrs}</li>
)
})}
<button>SEND ARR</button>
<ul className="qwe">
<li dangerouslySetInnerHTML={this.createMarkup()}></li>
</ul>
</div>
);
}
}
I'm brand new to Reactjs and I'm working on my first app, a todo app of course. However, everything was going smoothly until I was asked to create a delete button to remove my todos. I'm stuck and have been puzzled over this for almost 3 days. Any help or advice would be appreciated.
react-to-do/src/App.js
import React, { Component } from "react";
import "./App.css";
import ToDo from "./components/ToDo.js";
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{ description: "Walk the cat", isCompleted: true },
{ description: "Throw the dishes away", isCompleted: false },
{ description: "Buy new dishes", isCompleted: false }
],
newTodoDescription: ""
};
this.deleteTodo = this.deleteTodo.bind(this);
}
deleteTodo(description) {
this.setState({
todos: this.state.todos.filter(
(todos, index) => todos.description !== description
)
});
}
handleChange(e) {
this.setState({ newTodoDescription: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (!this.state.newTodoDescription) {
return;
}
const newTodo = {
description: this.state.newTodoDescription,
isCompleted: false
};
this.setState({
todos: [...this.state.todos, newTodo],
newTodoDescription: ""
});
}
toggleComplete(index) {
const todos = this.state.todos.slice();
const todo = todos[index];
todo.isCompleted = todo.isCompleted ? false : true;
this.setState({ todos: todos });
}
render() {
return (
<div className="App">
<ul>
{this.state.todos.map((todo, index) => (
<ToDo
key={index}
description={todo.description}
isCompleted={todo.isCompleted}
toggleComplete={() => this.toggleComplete(index)}
/>
))}
</ul>
<form onSubmit={e => this.handleSubmit(e)}>
<input
type="text"
value={this.state.newTodoDescription}
onChange={e => this.handleChange(e)}
/>
<input type="submit" />
</form>
</div>
);
}
}
export default App;
react-to-do/src/ToDo.js
import React, { Component } from "react";
class ToDo extends Component {
deleteToDo(description) {
this.props.deleteToDo(description);
}
render() {
return (
<div className="wrapper">
<button
className="deleteToDo"
onClick={e => this.deleteToDo(this.props.description)}
>
Delete
</button>
{this.props.deleteToDo}
<li>
<input
type="checkbox"
checked={this.props.isCompleted}
onChange={this.props.toggleComplete}
/>
<span>{this.props.description}</span>
</li>
</div>
);
}
}
export default ToDo;
react-to-do/src/index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import registerServiceWorker from "./registerServiceWorker";
ReactDOM.render(<App />, document.getElementById("root"));
registerServiceWorker();
Your code should look like
class ToDo extends React.Component {
deleteToDo(description) {
this.props.deleteToDo(description);
}
render() {
return (
<div className="wrapper">
<button className="deleteToDo" onClick = {(e) =>
this.deleteToDo(this.props.description)}>Delete</button>
{() => this.props.deleteToDo(this.props.description)}
<li>
<input type="checkbox" checked={ this.props.isCompleted }
onChange={ this.props.toggleComplete } />
<span>{ this.props.description }</span>
</li>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [
{ description: 'Walk the cat', isCompleted: true },
{ description: 'Throw the dishes away', isCompleted: false },
{ description: 'Buy new dishes', isCompleted: false }
],
newTodoDescription: ''
};
this.deleteTodo = this.deleteTodo.bind(this);
}
deleteTodo(description) {
const filteredTodos = this.state.todos.filter((todo, index) => todo.description !== description);
this.setState({
todos: filteredTodos
});
}
handleChange(e) {
this.setState({ newTodoDescription: e.target.value })
}
handleSubmit(e) {
e.preventDefault();
if (!this.state.newTodoDescription) { return }
const newTodo = { description: this.state.newTodoDescription,
isCompleted: false};
this.setState({ todos: [...this.state.todos, newTodo],
newTodoDescription: '' });
}
toggleComplete(index) {
const todos = this.state.todos.slice();
const todo = todos[index];
todo.isCompleted = todo.isCompleted ? false: true;
this.setState({ todos: todos });
}
render() {
return (
<div className="App">
<ul>
{ this.state.todos.map( (todo, index) =>
<ToDo key={ index } description={ todo.description }
isCompleted={ todo.isCompleted } toggleComplete={ () =>
this.toggleComplete(index) } deleteToDo={this.deleteTodo} />
)}
</ul>
<form onSubmit={ (e) => this.handleSubmit(e) }>
<input type="text" value={
this.state.newTodoDescription } onChange={ (e) =>
this.handleChange(e) } />
<input type="submit" />
</form>
</div>
);
}
}
Here you forgot to pass props from App and description parameter from ToDo component.
Try here https://jsfiddle.net/prakashk/69z2wepo/101369/#&togetherjs=B3l5GDzo8A
You never pass your "deleteTodo" function as a prop to your "toDo" component. change the portion where you create you're todo components in that map to resemble something like this...
map.... => <toDo deleteToDo={this.deleteTodo}......... />
remember components are scoped to themselves if you want to call a function that exists in the parents context in a child, a reference of that function must be passed to that child as a prop.
I have 2 files
App.js
import React, { Component } from 'react';
import './App.css';
import ToDo from './components/ToDo.js';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
newTodoDescription: ''
};
this.deleteTodo = this.deleteTodo.bind(this);
}
handleChange(e) {
this.setState({ newTodoDescription: e.target.value })
}
handleSubmit(e) {
e.preventDefault();
if (!this.state.newTodoDescription) { return }
const newTodo = { id: this.state.todos.id, description: this.state.newTodoDescription, isCompleted: false };
this.setState({ todos: [...this.state.todos, newTodo], newTodoDescription: '' });
}
toggleComplete(index) {
const todos = this.state.todos.slice();
const todo = todos[index];
todo.isCompleted = todo.isCompleted ? false : true;
this.setState({ todos: todos });
}
deleteTodo(id) {
const remainingToDos = this.state.todos.filter((todo, remainingToDos) => {
if(todo.id !== remainingToDos.id) return todo; });
this.setState({ todos: remainingToDos });
}
render() {
return (
<div className="App">
<h1>Add a ToDo!</h1>
<form onSubmit={ (e) => this.handleSubmit(e)}>
<input type="text"
value={ this.state.newTodoDescription }
onChange={ (e) => this.handleChange(e) }
/>
<input type="submit" value="Add Todo" />
</form>
<ul>
{ this.state.todos.map( (todo) =>
<ToDo key={ todo.id }
description={ todo.description }
isCompleted={ todo.isCompleted }
toggleComplete={ () => this.toggleComplete(todo) }
onDelete={ this.deleteTodo }
/>
)}
</ul>
</div>
);
}
}
export default App;
ToDo.js
import React, { Component } from 'react';
class ToDo extends Component {
render() {
return (
<li>
<input type="checkbox" checked={ this.props.isCompleted } onChange={ this.props.toggleComplete } />
<span>{ this.props.description } {''}</span>
<button onClick={() => this.props.onDelete(this.props.id)}>Remove Todo</button>
</li>
);
}
}
export default ToDo;
What I am trying to accomplish: Add many todos to the list. Click on the remove todo button. ONLY the todo that is selected will be removed.
I am VERY new to react and cannot figure this out. In my deleteToDo method I am trying to filter out the todos and only keep the todos that are current. I am unclear if I am using .filter properly or not.
Problem is that filter() method should return a condition, not value:
deleteTodo(id) {
const remainingToDos = this.state.todos.filter((todo, remainingToDos) => {
return (todo.id !== remainingToDos.id)
});
this.setState({ todos: remainingToDos });
}
I am fairly sure you have simply over-complicated your code. You are not using the parameter id that you have passed into your method at all. Your deleteTodo method could simply be:
deleteTodo = (id) => {
var remainingToDos = this.state.todos.filter((todo) => {
return todo.id === id
});
this.setState({ todos: remainingToDos })
}