Search code examples
javascriptreactjssortingreact-bootstrapstrikethrough

On click strike off items and move those items to the bottom of the list


I am trying to write a code where when a user clicks on an item on the list the item on that list should be strike off and and bring that item to the bottom of the list.

ItemList.js

 <ul className="list-group my-4">
        <h2 className="text-uppercase text-center custom-heading">todo list</h2>

        <div className="card card-body my-4 custom-card-bg">
          <pre>
            {items
              .slice(0)
              .reverse()
              .map(index => {
                return <ToDoItem key={index.id} name={index.name} />;
              })}
          </pre>
        </div>
      </ul>

The above given code is how the data is being added to the list

TodoItem.js

 <li className="list-group-item text-capitalize d-flex justify-content-between my-1 custom-input">
        <h6>{name}</h6>
        <div className="todo">
          <span className="mx-2 text-success">
            <i className="fas fa-pen" />
          </span>
          <span className="mx-2 text-danger">
            <i className="fas fa-trash" />
          </span>
        </div>
      </li>

The above code is the styling of the item

App.js

 class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          items: [],
          currentItem: {
            name: "",
            id: ""
          },
          editItem: false
        };
      }

    addItems = e => {
        e.preventDefault();
        const newItems = this.state.currentItem;
        if (newItems.name !== "") {
          const itemNames = [
            { ...newItems, isStriked: false },
            ...this.state.items
          ];
          this.setState({
            items: itemNames,
            currentItem: {
              name: "",
              id: ""
            },
            editItem: false
          });
        }
      };

      completedItem = id => {
        const complete = this.state.items.find(name => name.id === id);

        if (complete.isStriked === false)
          this.setState({
            items: [
              ...this.state.items.filter(name => name.id !== id),
              { ...complete, isStriked: true }
            ]
          });
      };

      render() {
        return (
          <div>
            <div
              className="container-fluid d-flex vh-100 flex-column"
              style={{ height: "100vh" }}
            >
              <div className="row">
                <div className="col-10 mx-auto col-md-8 mt-4 mb-2 custom-row-bg">
                  <h2 className="text-center text-uppercase mt-3 custom-heading">
                    input todo
                  </h2>
                  <InputItems
                    name={this.state.currentItem.name}
                    handleInputChanges={this.handleInputChanges}
                    addItems={this.addItems}
                  />
                  <ItemList
                    items={this.state.items}
                    completedItem={this.completedItem}
                  />
                </div>
              </div>
            </div>
          </div>
        );
      }
    }

    export default App;

The above mentioned code explains how i decided to work on the striking an item of the method , i am unable understand how to make it work in the ItemList component?


Solution

  • to have possibility to access onClick event in ItemList you need to make it ToDoItem component clickable:

    <ToDoItem
        onClick={() => {
          console.log(index);
        }}
        key={index.id}
        name={index.name}
    />
    

    In ToDoItem:

    In ToDoItem you are free to decide which element the click should start.

    //...
    const { name, onClick } = this.props;
    //...
       <li
            onClick={onClick}
            className="list-group-item text-capitalize d-flex justify-content-between my-1 custom-input"
          >
    //...
    

    Update:

    let { items } = this.state;
    let to = 0;
    let from = 0;
    items = items.map((item, index) => {
       if (item.id === id) {
         item.completed = true;
         from = index;
       }
       return item;
    });
    // here i'm move the object in top. Because you use revert array.
    // If you don't want to reverse array: to = items.length
    items.splice(to, 0, items.splice(from, 1)[0]);