Search code examples
reactjshtml-tablerow

When add new row of 2nd column , 1st row is row span in react.js


When click add button of 2nd column ,want to make 1st column rowspan And when click add button of 4th column, want to rowspan 1st and 2nd column. Please someone can help me.. I try 2 days but I don't know where i need .. My first use reactjs

Current result: Now Result

Expected result: Expected Result

addNewRow = (e) => {
        this.setState((prevState) => ({
            taskList: [...prevState.taskList, { index: Math.random(), softwareTable: "", task: "", taskNotes: "", taskStatus: "" }],
        }));
    }

return (
        props.taskList.map((val, idx) => {
            let softwareTable = `softwareTable-${idx}`, task = `task-${idx}`, taskNotes = `taskNotes-${idx}`, taskStatus = `taskStatus-${idx}`
            return (
                <tr key={val.index}>
                    <td>
                        <textarea name="softwareTable" data-id={idx} id={softwareTable} className="form-control " />
                        <button onClick={()=>props.add()} type="button" className="btn btn-primary text-center">+</button>
                        <button className="btn btn-danger" onClick={(() => props.delete(val))} >-</button>
                    </td>
                    <td>
                        <textarea name="task" id={task} data-id={idx} className="form-control " />
                        <button onClick={()=>props.add()} type="button" className="btn btn-primary text-center">+</button>
                        <button className="btn btn-danger" onClick={(() => props.delete(val))} >-</button>
                    </td>
                    <td>
                        <textarea name="taskNotes" id={taskNotes} data-id={idx} className="form-control"></textarea>
                        <button onClick={()=>props.add()} type="button" className="btn btn-primary text-center">+</button>
                        <button className="btn btn-danger" onClick={(() => props.delete(val))} >-</button>
                    </td>
                    <td>
                        <select name="taskStatus" id={taskStatus} data-id={idx} className="form-control" >
                            <option value="pending">Pending</option>
                            <option value="In Progress">In progress</option>
                        </select>
                    </td>

                </tr >
            )
        })
    )

render(){
return (

<tbody>
                                        <TaskList add={this.addNewRow} delete={this.clickOnDelete.bind(this)} taskList={taskList} />
                                        </tbody>
)
}

Solution

  • You obviously have a data hierarchy here (project -> task -> note).

    Here is a basic idea of how to render it in a table.

    Put your +/- buttons into cells, and insert/delete the corresponding objects on clicks, then re-render the component. Good luck :)

    const tableData = {
      projects: [
        {
          name: 'Project A',
          tasks: [
            {
              name: 'Task A1',
              notes: ['Note A1.1', 'Note A1.2']
            },
            {
              name: 'Task A2',
              notes: ['Note A2.1', 'Note A2.2', 'Note A2.3']
            },
            {
              name: 'Task A3',
              notes: ['Note A3.1']
            },
          ]
        },
        {
          name: 'Project B',
          tasks: [
            {
              name: 'Task B1',
              notes: ['Note B1.1']
            }
          ]
        }
      ]
    }
    
    const mapTask = task => {
        const notes = task.notes.map((note, index) => ({name: note, firstInTask: index === 0 ? task : null}));
      return {...task, notes};
    }
    
    const mapProject = project => {
        const tasks = project.tasks.map(mapTask);
      const projectNotes = tasks.reduce((all, task) => [...all, ...task.notes], []);
      const notes = projectNotes.map((note, index) => ({...note, firstInProject: index === 0 ? {...project, count: projectNotes.length} : null}));
      return {...project, tasks, notes};
    }
    
    const mapData = data => {
      const projects = data.projects.map(mapProject);
        const notes = projects.reduce((all, project) => [...all, ...project.notes], []);
      return {...data, projects, notes};
    };
    
    const Table = ({data}) => {
        const mappedData = mapData(data);
      console.log('MD: ', mappedData);
      
        return (
        <table cellSpacing="10" cellPadding="5">
         <tbody>
          {mappedData.notes.map(note => (
            <tr key={note.name}>
            {note.firstInProject && 
                <td rowSpan={note.firstInProject.count}>
                <span>{note.firstInProject.name}</span>
              </td>}
           {note.firstInTask && <td rowSpan={note.firstInTask.notes.length}>{note.firstInTask.name}</td>}
             <td>{note.name}</td>
            </tr>
          ))}
          </tbody>
        </table>
      );
    }
    
    ReactDOM.render(<Table data={tableData} />, document.getElementById('container'));
    td {
      border: 1px solid gray;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="container">
    </div>