koziiczkaa
koziiczkaa

Reputation: 3

How to add another table row on click in react app using typescript

I'm new with React and TypeScript. I want to add a new row in a table when someone clicks a button (FontAwesomeIcon). I actually don't even know where to start.

Here's my code

import React from "react";
import './SchemeFillData.scss';
import {faPlus} from "@fortawesome/free-solid-svg-icons/faPlus";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";

export function SchemeFillData() {
    return <div className='schemedata'>
            <table className='schemedata__attr'>
                <thead>
                <th className='schemedata__attr__title' colSpan={2}>
                    Atrybuty
                    <FontAwesomeIcon className='schemedata__add' icon={faPlus} size='lg' color='lightgray'/>
                </th>
                </thead>
                <tbody>
                <tr>
                    <td className='scheme__attr__cell'>
                        <input className='schemedata__input attr__input' placeholder='Nazwa atrybutu' type='text'
                               id='unit'/>
                    </td>
                    <td className='scheme__attr__cell'>
                        <select id="defVat" className='schemedata__select attr__select'>
                            <option value="" disabled selected>Wybierz kolumnę</option>
                        </select>
                    </td>
                </tr>
                </tbody>
            </table>
    </div>;
}

What do I need to do? Where to start? Thanks for the answers :)

Upvotes: 0

Views: 2203

Answers (3)

Maxime Oger
Maxime Oger

Reputation: 180

using typescript, you can do it like this :

I made a codesandbox demo if you want to check


    import React, { useState }from "react";
    import "./styles.css";
    
    // this type describe how the data of each rows should be shaped
    type RowData = {
      message: string;
    }

    // here we define an inteface to describe the shape of our component state
    // this is an object with a key 'rows' who contains an array of RowData
    interface IState {
      rows: RowData[];
    }
    
    export default function App() {
      // here we are controlling the parameters of useState function with our IState interface
      const [state, setState] = useState<IState>({rows: []});
    
      const addRow = () => {
        setState({
          rows: [...state.rows, { message: "my new element" }]
        })
      } 
    
      const { rows } = state;
    
      return (
        <div className='schemedata'>
          <table className='schemedata__attr'>
              <thead>
                <th className='schemedata__attr__title' colSpan={2}>
                    Atrybuty
                    <button onClick={addRow}>Add row</button>
                </th>
              </thead>
              <tbody>
                { rows.map(element => (
                    <tr> 
                      <td className='scheme__attr__cell'> 
                        <input className='schemedata__input attr__input' placeholder='Nazwa atrybutu' type='text' id='unit'/> 
                      </td> 
                      <td className='scheme__attr__cell'> 
                        <select id="defVat" className='schemedata__select attr__select'> 
                            <option value="" disabled selected>{element.message}</option> 
                        </select> 
                      </td> 
                    </tr>
                  ))
                }
              </tbody>
          </table>
        </div>
      );
    }

    enter code here

Upvotes: 0

VersifiXion
VersifiXion

Reputation: 2282

  1. You need to have a state property initialized with an empty array
  2. You need to bind a function to the button, which adds an object to this array
  3. In the JSX, you need to map on this array, and for every element in it, you add a tr tag with a td and a message in it

You can try something like this maybe :

import React, { useState } from "react";
import './SchemeFillData.scss';
import {faPlus} from "@fortawesome/free-solid-svg-icons/faPlus";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";

export function SchemeFillData() {
    const [array, setArray] = useState([]);

    function addNewRow() {
      setArray([...array, {}]);
    }

    return <div className='schemedata'>
            <table className='schemedata__attr'>
                <thead>
                <th className='schemedata__attr__title' colSpan={2}>
                    Atrybuty
                    <FontAwesomeIcon className='schemedata__add' icon={faPlus} size='lg' color='lightgray' onClick={addNewRow} />
                </th>
                </thead>
                <tbody>
                <tr>
                    <td className='scheme__attr__cell'>
                        <input className='schemedata__input attr__input' placeholder='Nazwa atrybutu' type='text'
                               id='unit'/>
                    </td>
                    <td className='scheme__attr__cell'>
                        <select id="defVat" className='schemedata__select attr__select'>
                            <option value="" disabled selected>Wybierz kolumnę</option>
                        </select>
                    </td>
                </tr>
                {array && array.map((_, index) => (
                  <tr key={index}> <td className='scheme__attr__cell'> <input className='schemedata__input attr__input' placeholder='Nazwa atrybutu' type='text' id='unit'/> </td> <td className='scheme__attr__cell'> <select id="defVat" className='schemedata__select attr__select'> <option value="" disabled selected>Wybierz kolumnę</option> </select> </td> </tr>
                )}
                </tbody>
            </table>
    </div>;
}

Upvotes: 1

Gabriel Tortomano
Gabriel Tortomano

Reputation: 115

Ok, you should read the react documentation to know how this frameworks work, but essentially, you need to render your "table-rows" from a state variable. So to make it simple to understand, lets say you have a variable rows=[]. You need to make a function that adds something to that row :

  const addRow = (someText) => {
    this.rows.push({content: someText}
  }

And you should call that function whenever someone clicks on your button. That will add a new object in your array. And if you have your rows mapped to that variable it should work as a basic version:

<tbody>
  {this.state.rows.map(( obj, index ) => {
      return (
        <tr key={index}>
          <td>{obj.content}</td>
        </tr>
      );
    })}
</tbody>

Upvotes: 0

Related Questions