pooja gajera
pooja gajera

Reputation: 383

Ternary condition on onclick event

I am trying to create a to-do application in React. Code I have so far adds to-do items to the to-do list. When I click on the edit icon I had put turnery condition for the done icon but it's not working. Can someone explain what is wrong with my code?

App.js

import './App.css';
import React, { useState } from 'react';
import TodoList from './TodoList';
import { v4 as uuidv4 } from 'uuid';

function App() {
  // const [input, setInput] = useState('');
  const [todos, setTodo] = useState([]);
  const input = React.useRef();

  const addTodo = (e) => {
    e.preventDefault();
    const id = uuidv4();
    setTodo([...todos, { id: id, text: input.current.value }]) 
    input.current.value='';
  } 

  const deleteTodo = (id) => {
    setTodo(todos.filter(todo => todo.id !== id));
  }

  const editTodo = (id) => {
    
  }

  return ( 
    <div className="App">
      <form>
        <input type="text" ref={input}/>
        <button type="submit" onClick={addTodo}>Enter</button>
      </form>
      <TodoList todos={todos} deleteTodo={deleteTodo} editTodo={editTodo}/>
    </div>
  );
}

export default App;

TodoItem.js

import React from 'react'
import DeleteIcon from '@material-ui/icons/Delete';
import EditIcon from '@material-ui/icons/Edit';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import DoneIcon from '@material-ui/icons/Done';

const TodoItem = ({todo, deleteTodo, editTodo}) => {
    return (
        <>
            <div>
                <CheckBoxOutlineBlankIcon/>
                <input type="text" value={todo.text} readOnly={true}/>
            </div>
            <div>
               { <EditIcon/> ? <EditIcon onClick={editTodo}/> : <DoneIcon/> }
               <DeleteIcon onClick={deleteTodo}/>
            </div>
        </>
    )
}

export default TodoItem

Upvotes: 0

Views: 1366

Answers (2)

codemonkey
codemonkey

Reputation: 7935

There are a few problems with your code. One, also pointed out by Abu Sufian is that your ternary operator will always trigger whatever is immediately after ?, because <EditIcon/> is just a component and will always be true.

But more fundamentally, to do what you want, you will need to add another properly to your todo list, say, status. So when a task goes in for the first time, it will be in pending status, then once you click your Edit icon, it will change to done. And that's how we will toggle that icon with a ternary operator.

So I would change your addTodo function to

  const addTodo = (e) => {
    e.preventDefault();
    const id = uuidv4();
    setTodo([
      ...todos,
      { id: id, text: input.current.value, status: "pending" }
    ]);
    input.current.value = "";
  };

Then I would change your editTodo to:

  const editTodo = (id) => {
    console.log(id);
    setTodo(
      todos.map((todo) => {
        if (todo.id === id) todo.status = "done";

        return todo;
      })
    );
  };

And finally, I would change your ternary part to:

{todo.status === "pending" ? (
          <EditIcon onClick={() => editTodo(todo.id)} />
        ) : (
          <DoneIcon />
        )}

Here is a complete Sandbox for you. Sorry I don't have your CSS so I can't make it look super pretty.

Upvotes: 1

sadrzadehsina
sadrzadehsina

Reputation: 1349

Maybe you are looking for something like this.

{ !todo.done ? <EditIcon onClick={editTodo}/> : <DoneIcon/> }

I believe checking whether a todo item is done or not should happen with a property of todo object itself.

In a ternary you need to start with a condition.

condition ? do something when true : do something when false

So you have to have a condition in the first place. In your case EditIcon is not a condition.

If you are looking for a way to mark a todo as completed so you need to do more things.

const markAsCompleted = id => {
  const todo = todos.find(todo => todo.id !== id);
  setTodo([...todos, {...todo, done: true }]);
}

Then you can decide based on whether a todo is done or not.

Upvotes: 1

Related Questions