PatrickGoethe
PatrickGoethe

Reputation: 35

add row on button press React

im trying to add a row to a table, on a click event. Here is my component:

import React, { Component } from 'react';
import PageContent from 'components/PageContent';
import { IBox, IBoxTitle, IBoxContent } from 'components/IBox';
import IBoxTools from 'components/IBoxTools';
import Table from 'components/Table';

export default class SalesChannelsPage extends Component {
    constructor(props) {
        super(props);
        this.addRow = this.addRow.bind(this);
    }

    render() {
        return (
            <PageContent header="Salgskanaler">
                <IBox> 
                    <IBoxTitle>
                        Salgskanaler
                        <IBoxTools icon="fa fa-plus" title="Tilføj salgskanal" handleClick={() => this.addRow()}/>
                    </IBoxTitle>
                    <IBoxContent>
                        <Table>
                            <thead>
                                <tr>
                                    <td className="channel-name">Navn</td>
                                    <td className="channel-description">Beskrivelse</td>
                                    <td className="channel-btn"></td>
                                </tr>
                            </thead>
                            <tbody>

                            </tbody>
                        </Table>
                    </IBoxContent>
                </IBox>
            </PageContent>
        );
    }

    addRow() {
        console.log('add row')
    }
}

So everytime i click the button, a new row should be added, and it should be possible to add as many rows to the list as possible. here is the row i want to add.

i realize that i could make an array in state and just put it there, but i have learned that only the data should be contained in the state. Some help would be much appreciated. Thx

<tr>
    <td className="channel-name">
        <input className="form-control input-sm" type="text" placeholder="Navn..." />
    </td>
    <td className="channel-description">
        <input className="form-control input-sm" type="text" placeholder="Beskrivelse..." />
    </td>
    <td className="channel-btn">
        <div>
            <div className="btn btn-xs btn-danger"><span className="fa fa-times"></span></div>
            <div className="btn btn-xs btn-primary"><span className="fa fa-floppy-o"></span></div>
        </div>
    </td>
</tr>

Upvotes: 1

Views: 12532

Answers (1)

aray12
aray12

Reputation: 1843

So as Matthew Herbst said, this is what state is for. Presumably those rows need to display some kind of data. You shouldn't be storing the HTML/JSX in the array, but you should be storing the data used to construct the list in the array. This is what is great about React. You declare how the UI should be presented based on the underlying data. Then you just manipulate the data. So first you need an array in your state that represents the list. Also, you don't need to declare your addRow handler as being returned by a function. It is a function. Just pass the function without invoking it by excluding the () parentheses. Finally, you map over the array, returning the rows. Obviously this is all kind of dump without data, but it is immediately clear what data you want in the rows. So it should look something like this:

import React, { Component } from 'react';
import PageContent from 'components/PageContent';
import { IBox, IBoxTitle, IBoxContent } from 'components/IBox';
import IBoxTools from 'components/IBoxTools';
import Table from 'components/Table';

export default class SalesChannelsPage extends Component {
    constructor(props) {
        super(props);
        this.addRow = this.addRow.bind(this);
        this.state = {
          rows: []
        }
    }

    render() {
        return (
            <PageContent header="Salgskanaler">
                <IBox> 
                    <IBoxTitle>
                        Salgskanaler
                        <IBoxTools icon="fa fa-plus" title="Tilføj salgskanal" handleClick={this.addRow}/>
                    </IBoxTitle>
                    <IBoxContent>
                        <Table>
                            <thead>
                                <tr>
                                    <td className="channel-name">Navn</td>
                                    <td className="channel-description">Beskrivelse</td>
                                    <td className="channel-btn"></td>
                                </tr>
                            </thead>
                            <tbody>
                              {this.state.rows.map(row => <tr></tr>)}
                            </tbody>
                        </Table>
                    </IBoxContent>
                </IBox>
            </PageContent>
        );
    }

    addRow() {
        var nextState = this.state;
        nextState.rows.push('placeholder');
        this.setState(nextState);
    }
}

Again I am just pushing the text placeholder to the end of the array each time because I don't know what data you want in there. But this will keep generate empty <tr> tags for you on each push of the button.

Upvotes: 5

Related Questions